在循环

时间:2016-12-13 22:51:07

标签: java spring hibernate jta

我有一个使用Spring,Hibernate和JTA的应用程序。

我们收到的请求数据大于预期(10000个元素),一般请求数为10-100个元素。

在处理此请求时,我们尝试在DB中为每个元素插入一条记录,并在for循环中完成

伪代码:

processRecords( list){

for (Element element: list){

dao.findBy -- This takes around 100 ms

-- some other checks and logic

dao.add(element); -- This takes around 150 ms
dao.flush();
 }

}

此块需要花费大量时间来处理记录,然后我得到*

  

“javax.persistence.TransactionRequiredException:没有任何交易   进展“

*

我尝试将刷新移出for循环,没有帮助,我尝试研究hibernate的批量插入,但这是一个庞大的应用程序,有很多自定义,我不认为这是一个选项,因为它会影响整个应用程序,我也尝试找到配置的事务持续时间,只有我能找到的地方是在weblogic上的JTA,它设置为480秒。

非常感谢任何有关如何解决这种情况的指标。

编辑: 增加weblogic中的JTA Timeout暂时解决了这个问题,但我把它设置为一个非常大的值5000秒,无论如何都有提高性能,因为我只是插入8K记录(我知道批处理是一个选项,但那里围绕着自定义“框架”的一些约束

2 个答案:

答案 0 :(得分:8)

使用@Transactional来控制交易。

  1. 确保不会使用PROPAGATION_NEVER
  2. 自动启动交易
  3. 通过使用REQUIRES_NEW调用服务方法,为列表中的每个项目(或列表中的项目子集)启动新事务。
  4. 在第二步中,您可能希望调用另一个bean以便实际拾取事务注释,不记得这是否适用于同一对象上的方法。

答案 1 :(得分:2)

根据您的内联通知,您的交易持续时间为2,500秒,其中1,000秒正在读取数据库,1,500正在添加到数据库。

您可以通过稍微重构逻辑来减少数据库事务:在大多数数据库驱动程序中,数据库实际上不会在第一次“写入”数据库之前启动事务。您可以通过重构逻辑来首先执行所有读取,然后执行所有写操作来利用此功能。我使用非JPA数据访问方法取得了成功,但是没有尝试过JPA。重构的伪代码是这样的:

processRecords( list){

// do all the reads
List adds=new ...
for (Element element: list){
  dao.findBy -- This takes around 100 ms
  -- some other checks and logic
  adds.put(element);
}

// do all the writes
for (Element element: adds){
  dao.add(element); -- This takes around 150 ms
  dao.flush();
 }

}

使用数据库跟踪验证这是否按预期工作。除了减少事务持续时间之外,此方法还可以降低因另一个线程上的读取而导致阻塞的风险。