我有一个使用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记录(我知道批处理是一个选项,但那里围绕着自定义“框架”的一些约束
答案 0 :(得分:8)
使用@Transactional来控制交易。
在第二步中,您可能希望调用另一个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();
}
}
使用数据库跟踪验证这是否按预期工作。除了减少事务持续时间之外,此方法还可以降低因另一个线程上的读取而导致阻塞的风险。