我正在使用Mysql,Spring Data JPA。在我的用例中,我只有1个表,例如客户(ID,FIRST_NAME,LAST_NAME) 我想要实现的是在批量/批量更新中,其中更新语句是一组,如示例所示,以减少数据库往返行程。
我已经设置了所有属性
但是结果是(更新语句未分组): MySQL常规日志中的日志
2018-10-28T03:18:32.545233Z 1711 Query update CUSTOMER set FIRST_NAME=’499997′, LAST_NAME=’499998′ where id=499996;
2018-10-28T03:18:32.545488Z 1711 Query update CUSTOMER set FIRST_NAME=’499998′, LAST_NAME=’499999′ where id=499997;
2018-10-28T03:18:32.545809Z 1711 Query update CUSTOMER set FIRST_NAME=’499999′, LAST_NAME=’500000′ where id=499998;
所需结果:(将更新分组为单个查询,从而减少了数据库往返次数)
2018-10-28T03:18:32.545233Z 1711 Query update CUSTOMER set FIRST_NAME=’499997′, LAST_NAME=’499998′ where id=499996; update CUSTOMER set FIRST_NAME=’499998′, LAST_NAME=’499999′ where id=499997; update CUSTOMER set FIRST_NAME=’499999′, LAST_NAME=’500000′ where id=499998;
我的应用程序需要执行超过1亿次更新,我想这可能是最快的方法。
答案 0 :(得分:-1)
我建议您也设置hibernate.jdbc.batch_size
属性。以下是我尝试过的一个小例子:
int entityCount = 50;
int batchSize = 25;
EntityManager entityManager = entityManagerFactory()
.createEntityManager();
EntityTransaction entityTransaction = entityManager
.getTransaction();
try {
entityTransaction.begin();
for (int i = 0; i < entityCount; i++) {
if (i > 0 && i % batchSize == 0) {
entityTransaction.commit();
entityTransaction.begin();
entityManager.clear();
}
Post post = new Post(
String.format("Post %d", i + 1)
);
entityManager.persist(post);
}
entityTransaction.commit();
} catch (RuntimeException e) {
if (entityTransaction.isActive()) {
entityTransaction.rollback();
}
throw e;
} finally {
entityManager.close();
}
每次迭代计数器(例如i)都达到batchSize阈值的倍数时,我们可以刷新EntityManager并提交数据库事务。通过在每次批处理执行之后提交数据库事务,我们获得了以下优点:
在每次执行批处理后都会清除EntityManager,以免我们继续积累会导致多个问题的托管实体:
如果引发异常,则必须确保回滚当前正在运行的数据库事务。否则,可能会导致许多问题,因为数据库可能仍然认为事务已打开并且锁可能会一直保留,直到事务因超时或DBA而终止。
最后,我们需要关闭EntityManager以便清除上下文并取消分配会话级资源。