Java Spring引导和Hibernate事务未按预期工作
我有一个MySql上带有Hibernate的Spring启动应用程序,我需要对一些服务使用一些悲观的锁定逻辑 我有一个计划好的作业,它应该更新一些对象,但是接下来的迭代没有考虑前一个,所以我想对服务使用悲观的逻辑 所以,这是预定的任务Java Spring引导和Hibernate事务未按预期工作,java,spring,hibernate,Java,Spring,Hibernate,我有一个MySql上带有Hibernate的Spring启动应用程序,我需要对一些服务使用一些悲观的锁定逻辑 我有一个计划好的作业,它应该更新一些对象,但是接下来的迭代没有考虑前一个,所以我想对服务使用悲观的逻辑 所以,这是预定的任务 @Scheduled(fixedDelay=3000, initialDelay=5000) public void checkSwitchToShutDown(){ // logger.debug("scheduled partito :"+ date
@Scheduled(fixedDelay=3000, initialDelay=5000)
public void checkSwitchToShutDown(){
// logger.debug("scheduled partito :"+ dateFormat.format(new Date()));
List<Interruttore> interruttori = interruttoreService.findAllSwitches();
for (int i = 0; i < interruttori.size(); i++){
Interruttore interruttore = interruttori.get(i);
interruttoreService.toggleSwitchNew(interruttore);
}
}
updateInterruttore
@Override
@Transactional(readOnly = false, isolation = Isolation.SERIALIZABLE)
public void updateInterruttore(Interruttore interruttore) {
try {
Interruttore entity = dao.findById(interruttore.getIdInterruttore());
if (entity != null) {
entity.setStato(interruttore.isStato());
entity.setDateTime(interruttore.getDateTime());
entity.setTimeoutDate(interruttore.getTimeoutDate());
}
} catch (Throwable t) {
logger.debug("Error: ",t);
}
}
现在,计划任务的两个连续步骤进入toggleSwitchNew
,即使第一个步骤将开关的状态更改为true,第二个步骤也会将该值设置为false,因为事务未被锁定
例如,这是一个发生了什么的日志:
2016-11-08 13:03:03 DEBUG InterruttoreServiceImpl:173 [pool-2-thread-1] - status at the beginning false
2016-11-08 13:03:03 DEBUG InterruttoreServiceImpl:177 [pool-2-thread-1] - updated status true
2016-11-08 13:03:03 DEBUG InterruttoreServiceImpl:183 [pool-2-thread-1] - L'interruttore si deve accendere: Zona -4B
2016-11-08 13:03:07 DEBUG InterruttoreServiceImpl:173 [pool-2-thread-1] - status at the beginning false
2016-11-08 13:03:07 DEBUG InterruttoreServiceImpl:177 [pool-2-thread-1] - updated status true
2016-11-08 13:03:07 DEBUG InterruttoreServiceImpl:183 [pool-2-thread-1] - L'interruttore si deve accendere: Zona -4B
为什么会有所不同呢?您在
updateInterruttore
上的@Transactional
非常无用,因为它是一个内部方法调用,因为Spring使用代理来应用AOP,没有任何事务应用。实际上,当您在分离的实体上操作时,任何东西都不会被持久化。如果你真的想修复它,事务性方法实际上应该是你的@Scheduled
方法,而不是单独的方法调用。你在数据库上的具体操作位置是什么?我在服务层下有一个DAO,它与数据库一起运行,但更新只在服务中,因为我以为Hibernate会用transaction@M.Deinum为什么你说什么都不会坚持?如果我没有2个并发请求,那么当您没有显示所有内容时,数据库将正确更新。然而,您的事务划分仍然是错误的,您的整个计划方法应该是事务性的。问题是,您正在读取内容,然后在单个事务中重新读取,因此序列化的数据很短,旧线程仍然具有旧的读取数据(使用find all)。为什么会有所不同?您在updateInterruttore
上的@Transactional
非常无用,因为它是一个内部方法调用,因为Spring使用代理来应用AOP,没有任何事务应用。实际上,当您在分离的实体上操作时,任何东西都不会被持久化。如果你真的想修复它,事务性方法实际上应该是你的@Scheduled
方法,而不是单独的方法调用。你在数据库上的具体操作位置是什么?我在服务层下有一个DAO,它与数据库一起运行,但更新只在服务中,因为我以为Hibernate会用transaction@M.Deinum为什么你说什么都不会坚持?如果我没有2个并发请求,那么当您没有显示所有内容时,数据库将正确更新。然而,您的事务划分仍然是错误的,您的整个计划方法应该是事务性的。问题是,您正在读取内容,然后在单个事务中重新读取,因此序列化的数据很短,旧线程仍然具有旧的读取数据(使用find all)。
2016-11-08 13:03:03 DEBUG InterruttoreServiceImpl:173 [pool-2-thread-1] - status at the beginning false
2016-11-08 13:03:03 DEBUG InterruttoreServiceImpl:177 [pool-2-thread-1] - updated status true
2016-11-08 13:03:03 DEBUG InterruttoreServiceImpl:183 [pool-2-thread-1] - L'interruttore si deve accendere: Zona -4B
2016-11-08 13:03:07 DEBUG InterruttoreServiceImpl:173 [pool-2-thread-1] - status at the beginning false
2016-11-08 13:03:07 DEBUG InterruttoreServiceImpl:177 [pool-2-thread-1] - updated status true
2016-11-08 13:03:07 DEBUG InterruttoreServiceImpl:183 [pool-2-thread-1] - L'interruttore si deve accendere: Zona -4B