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

标签 java database spring hibernate persistence

我有一个由 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/

相关文章:

java - 如何使用java + selenium设置chrome浏览器语言?

java - 无法在另一个矩形上绘画

java - 如何在我的设置 Activity 中添加主题?

java - 持久化新元素时违反唯一索引或主键

java - 有 Spring PHP 项目吗?

java - Swing 动画问题?

mysql - 如何选择轨道中每条记录之间间隔不大于5分钟的记录?

跨多个表的 MySQL 关键字搜索

php - Apache2 mod_ruid2 和 Document ChRoot — 无法连接到 MySQL 数据库

java - 如何将 PostgreSQL 数据源添加到 Java Spring REST API 项目中?