gpt4 book ai didi

java - 优化一些后续 Hibernate 加载/保存调用的想法

转载 作者:太空宇宙 更新时间:2023-11-04 06:39:52 25 4
gpt4 key购买 nike

我有一个由 Hibernate 备份的简单存储库

@Repository
@Transactional(rollbackFor = Exception.class)
public class WidgetDAOImpl implements WidgetDAO {
@Autowired
private SessionFactory sf;

@Override
public Widget getWidget(long id) {
return (Widget) sf.getCurrentSession().load(Widget.class, id);
}

@Override
public void saveWidget(Widget w){
sf.getCurrentSession().saveOrUpdate(w);
}
}

这真的很简单,而且还可以。不幸的是,需求发生了变化,现在我需要在一次业务通话期间阅读大量内容并保存大量小部件。此外,业务电话的数量也会增加。

例如,这可能是单独类中的业务逻辑:

@Scheduled(fixedDelay = 100L)                       // lets say this is "often"
public void updateWidgets(List<Long> ids){ // lets say the list is ~10 ids
for(long id: ids){
Widget w = widgetDAO.getWidget(id);
doSomeStuff(w);
widgetDAO.saveWidget(w);
}
}

我担心这会影响性能。我该怎么做才能节省性能?

  • 我应该批量加载/保存,即一次性加载/保存吗?我有 ID 列表,所以也许有可能?
  • 我是否应该以 session 以外的方式缓存实例(如您所见, session 很短)?

一些想法/片段非常受欢迎,因为我是一个 Hibernate 新手。

最佳答案

您当前的解决方案正在创建大量事务。每个项目 2 个事务,1 个用于读取,1 个用于写入。

创建事务(通常)是一项繁重且耗时的操作,因为它将打开与数据库的连接,启动 hibernate session 并进行一些同步。

最好您的整个方法是一个事务,这可以通过使用 @Transactional 注释您的方法来完成。

@Scheduled(fixedDelay = 100L)              
@Transactional
public void updateWidgets(List<Long> ids){ ... }

执行此操作时,如果您有大量数据,您可能需要偶尔刷新清除当前 session 。

如果您不希望这样,您至少应该在单个事务中进行读取和写入。为此,您可以使用 TransactionTemplate 并在 for 循环中使用它。

@Autowired
private TransactionTemplate transactionTemplate;

@Scheduled(fixedDelay = 100L)
public void updateWidgets(List<Long> ids) {
for(long id: ids){
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
Widget w = widgetDAO.getWidget(id);
doSomeStuff(w);
widgetDAO.saveWidget(w);
}
}
}

或者将 for 循环中的代码移至用 @Transactional 注释的服务方法。

关于java - 优化一些后续 Hibernate 加载/保存调用的想法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24817643/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com