已计划 Spring MVC 任务未更新数据库实体
Scheduled Spring MVC task not updating DB entity
早上好,
我正在尝试创建一个必须周期性更新数据库实体的计划任务,我正在使用 Spring MVC 和 Hibernate 作为 ORM。
问题
计划任务应在后台更新实体,但更改不会保存在数据库中。
系统结构
我有一个 Batch
实体,其中包含基本信息和大量传感器,每隔几秒就会在数据库中插入记录。
与Batch
实体相关,有一个TrackedBatch
实体,其中包含很多与Batch
实体本身相关的计算字段,计划任务将每个Batch
一个接一个,使用 lotto = lottoService.updateBatchRelations(batch)
更新来自传感器的相关数据,然后使用新的计算数据更新 TrackedBatch
实体。
用户可以修改Batch
基本信息,然后系统应该重新计算TrackedBatch
数据并更新实体(这是由调用updateBatchFollowingModification
方法的控制器完成的)。这一步是用异步方法正确完成的,当计划任务应该重新计算相同的信息时就会出现问题。
用于在用户修改后更新实体的异步方法(工作正常)
@Async("threadPoolTaskExecutor")
@Transactional
public void updateBatchFollowingModification(Lotto lotto)
{
logger.debug("Daemon started");
Lotto batch = lottoService.findBatchById(lotto.getId_lotto(), false);
lotto = lottoService.updateBatchRelations(batch);
lotto.setTrackedBatch(trackableBatchService.modifyTrackedBatch(batch.getTrackedBatch(), batch));
logger.debug("Daemon ended");
}
循环更新实体的预定方法(未按预期工作)
@Scheduled(fixedDelay = 10000)
public void updateActiveBatchesWithDaemon()
{
logger.info("updating active batches in background");
List<Integer> idsOfActiveBatches = lottoService.findIdsOfActiveBatchesInAllSectors();
if(!idsOfActiveBatches.isEmpty())
{
logger.info("found " + idsOfActiveBatches.size() + " active batches");
for(Integer id : idsOfActiveBatches)
{
logger.debug("update batch " + id + " in background");
updateBatch(id);
}
}
else
{
logger.info("no active batches found");
}
}
@Transactional
public void updateBatch(Integer id)
{
Lotto activeLotto = lottoService.findBatchById(id, false);
updateBatchFollowingModification(activeLotto);
}
作为前提,我可以声明调度方法 fired/configured 正确并且连续运行(同样代表异步方法,因为在用户修改后所有实体都正确更新),在行 updateBatchFollowingModification(activeLotto)
在 updateBatch
方法中,相关实体被正确修改(甚至 TrackedBatch
,我已经用调试器检查过),然后当方法结束时,更改不会保存在数据库中,也不会抛出异常.
环顾互联网,我没有找到任何解决这个问题的方法,也似乎是 Hibernate 和 Spring.
的已知问题或错误
同时阅读 Spring 有关计划的文档也没有帮助,我还尝试在计划任务中使用 save
方法再次保存实体(但显然没有用)。
进一步考虑
我不知道 @Scheduled
注释是否需要一些额外的配置来处理 @Transactional
方法,因为在网络开发人员中使用这些注释没有问题,而且在文档中没有提到缺点.
我也不认为这是并发问题,因为如果异步方法正在修改数据,那么预定的应该被隐式乐观锁定系统停止以便在第一次事务提交后完成,同样如果第一个获得锁定的是预定方法(如果我错了请纠正我)。
我无法弄清楚为什么在使用预定方法时更改没有持久化,有人可以 link 关于这个主题的文档或教程吗?这样我就可以找到解决方案,或者,更好的是,如果有人遇到类似的问题,如何解决?
最后,我通过显式定义流程中涉及的事务的隔离级别并消除 updateBatch
方法(因为它是一种重复的功能,如 updateBatchFollowingModification
设法解决了这个问题正在做同样的事情),特别是我将 updateBatchFollowingModification
的隔离级别设置为 @Transactional(isolation = Isolation.SERIALIZABLE)
.
这显然适用于我的情况,因为不需要可伸缩性,因此序列化操作不会给应用程序带来任何问题。
早上好,
我正在尝试创建一个必须周期性更新数据库实体的计划任务,我正在使用 Spring MVC 和 Hibernate 作为 ORM。
问题
计划任务应在后台更新实体,但更改不会保存在数据库中。
系统结构
我有一个 Batch
实体,其中包含基本信息和大量传感器,每隔几秒就会在数据库中插入记录。
与Batch
实体相关,有一个TrackedBatch
实体,其中包含很多与Batch
实体本身相关的计算字段,计划任务将每个Batch
一个接一个,使用 lotto = lottoService.updateBatchRelations(batch)
更新来自传感器的相关数据,然后使用新的计算数据更新 TrackedBatch
实体。
用户可以修改Batch
基本信息,然后系统应该重新计算TrackedBatch
数据并更新实体(这是由调用updateBatchFollowingModification
方法的控制器完成的)。这一步是用异步方法正确完成的,当计划任务应该重新计算相同的信息时就会出现问题。
用于在用户修改后更新实体的异步方法(工作正常)
@Async("threadPoolTaskExecutor")
@Transactional
public void updateBatchFollowingModification(Lotto lotto)
{
logger.debug("Daemon started");
Lotto batch = lottoService.findBatchById(lotto.getId_lotto(), false);
lotto = lottoService.updateBatchRelations(batch);
lotto.setTrackedBatch(trackableBatchService.modifyTrackedBatch(batch.getTrackedBatch(), batch));
logger.debug("Daemon ended");
}
循环更新实体的预定方法(未按预期工作)
@Scheduled(fixedDelay = 10000)
public void updateActiveBatchesWithDaemon()
{
logger.info("updating active batches in background");
List<Integer> idsOfActiveBatches = lottoService.findIdsOfActiveBatchesInAllSectors();
if(!idsOfActiveBatches.isEmpty())
{
logger.info("found " + idsOfActiveBatches.size() + " active batches");
for(Integer id : idsOfActiveBatches)
{
logger.debug("update batch " + id + " in background");
updateBatch(id);
}
}
else
{
logger.info("no active batches found");
}
}
@Transactional
public void updateBatch(Integer id)
{
Lotto activeLotto = lottoService.findBatchById(id, false);
updateBatchFollowingModification(activeLotto);
}
作为前提,我可以声明调度方法 fired/configured 正确并且连续运行(同样代表异步方法,因为在用户修改后所有实体都正确更新),在行 updateBatchFollowingModification(activeLotto)
在 updateBatch
方法中,相关实体被正确修改(甚至 TrackedBatch
,我已经用调试器检查过),然后当方法结束时,更改不会保存在数据库中,也不会抛出异常.
环顾互联网,我没有找到任何解决这个问题的方法,也似乎是 Hibernate 和 Spring.
的已知问题或错误同时阅读 Spring 有关计划的文档也没有帮助,我还尝试在计划任务中使用 save
方法再次保存实体(但显然没有用)。
进一步考虑
我不知道 @Scheduled
注释是否需要一些额外的配置来处理 @Transactional
方法,因为在网络开发人员中使用这些注释没有问题,而且在文档中没有提到缺点.
我也不认为这是并发问题,因为如果异步方法正在修改数据,那么预定的应该被隐式乐观锁定系统停止以便在第一次事务提交后完成,同样如果第一个获得锁定的是预定方法(如果我错了请纠正我)。
我无法弄清楚为什么在使用预定方法时更改没有持久化,有人可以 link 关于这个主题的文档或教程吗?这样我就可以找到解决方案,或者,更好的是,如果有人遇到类似的问题,如何解决?
最后,我通过显式定义流程中涉及的事务的隔离级别并消除 updateBatch
方法(因为它是一种重复的功能,如 updateBatchFollowingModification
设法解决了这个问题正在做同样的事情),特别是我将 updateBatchFollowingModification
的隔离级别设置为 @Transactional(isolation = Isolation.SERIALIZABLE)
.
这显然适用于我的情况,因为不需要可伸缩性,因此序列化操作不会给应用程序带来任何问题。