java - 在具有更新值的事务中保存相同的实例两次
问题描述
我正在 Spring Boot 中编写多线程 cron 作业。我有一个需要对其执行某些操作的用户列表。以下是 cron 作业的片段
public void executeCronJob() {
LOG.debug("Started >>>");
User user = userService.findFirstNotInProgress();
if (user == null) {
LOG.debug("<<< User not found");
return;
}
userService.updateStatus(user, Status.IN_PROGRESS);
someOtherService.doSomeActionRelatedToUser(user);
userService.updateStatus(user, Status.COMPLETED);
LOG.debug("<<< Completed");
}
在UserService.java中
private void updateStatus(User user, Status status) {
user.setStatus(status);
userRepository.save(user);
}
我正在使用多线程,因为该someOtherService.doSomeActionRelatedToUser(user);
方法可能需要相当长的时间,因此会阻止其他用户的执行。第一次调用userService.updateStatus
工作正常,用户进入IN_PROGRESS状态。但是在执行someOtherService
与用户相关的操作后,当我userService.updateStatus
再次调用以将状态设置为COMPLETED时,出现错误
行被另一个事务更新或删除(或未保存值映射不正确)
我曾尝试userRepository.saveAndFlush(user);
在 UserService 中使用,但它仍然给我同样的错误。我该如何解决这个问题?
解决方案
您正在将user
与会话相关联的传递给多个线程,并且由于 Hibernate Session 对象不是线程安全的,因此您最终会遇到此错误。
doSomeActionRelatedToUser()
您可以使用新会话而不是 from将状态更新为 COMPLETED executeCronJob()
。
或者您可能想要someOtherService.doSomeActionRelatedToUser(user);
返回CompletableFuture
然后更新状态。
希望能帮助到你。
推荐阅读
- sql - 在 SQL Server 中使用 IF 循环打印警告语句
- kubernetes - 将节点端口添加到令人兴奋的 istio 服务
- c# - 简单继承在项目之间不起作用
- sql - 在 Oracle 中使用 Round 时结果不一致
- c# - WebApi c#rest web service不能传递对象列表
- android - Smali toString() 不适用于给定的参数对象
- search - NoSQL - 如何正确实现自动建议和最佳匹配?
- java - Spring 事务在 RuntimeException 上回滚
- jquery - 语义 UI 完整的类列表/文档
- reporting-services - SSRS express 2017,配置管理器不连接服务;RPC 问题