Java 使用更新的值在事务中保存同一实例两次

Java 使用更新的值在事务中保存同一实例两次,java,multithreading,spring-boot,cron,transactions,Java,Multithreading,Spring Boot,Cron,Transactions,我正在SpringBoot中编写一个多线程cron作业。我有一个需要执行某些操作的用户列表。下面是by cron作业的一个片段 public void executeCronJob() { LOG.debug("Started >>>"); User user = userService.findFirstNotInProgress(); if (user == null) { LOG.debug("<<< User n

我正在SpringBoot中编写一个多线程cron作业。我有一个需要执行某些操作的用户列表。下面是by 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");
}
我使用多线程是因为
someOtherService.doSomeActionRelatedToUser(用户)方法可能需要相当长的时间,因此会阻止其他用户执行。对
userService.updateStatus的第一次调用工作正常,用户进入in\u PROGRESS状态。但是在对与用户相关的
someOtherService
执行操作后,当我再次调用
userService.updateStatus
以将状态设置为COMPLETED时,我得到了错误

行被另一个事务更新或删除(或未保存的值映射不正确)


我尝试使用user
userRepository.saveAndFlush(user),但它仍然给我相同的错误。如何解决此问题?

我认为您需要确保只有一个线程访问[下面给出的]代码块,以获取用户状态并将状态更新为进行中。您必须同步下面的代码块

User user = userService.findFirstNotInProgress();
if (user == null) {
    LOG.debug("<<< User not found");
    return;
}
userService.updateStatus(user, Status.IN_PROGRESS);
User User=userService.findFirstNotInProgress();
if(user==null){

LOG.debug(“我认为您需要确保只有一个线程访问[下面给出的]代码块,以获取用户状态并将状态更新为进行中。您必须同步下面的代码块

User user = userService.findFirstNotInProgress();
if (user == null) {
    LOG.debug("<<< User not found");
    return;
}
userService.updateStatus(user, Status.IN_PROGRESS);
User User=userService.findFirstNotInProgress();
if(user==null){

LOG.debug(“您正在将与会话相关联的
用户
传递给多个线程,并且由于Hibernate会话对象不是线程安全的,因此会出现此错误

您可以使用新会话在
doSomeActionRelatedToUser()
中将状态更新为COMPLETED,而不是从
executeCronJob()

或者您可能希望
someOtherService.doSomeActionRelatedToUser(用户);
返回
CompletableFuture
,然后更新状态


希望有帮助。

您正在将与会话相关的
用户
传递给多个线程,并且由于Hibernate会话对象不是线程安全的,您最终会出现此错误

您可以使用新会话在
doSomeActionRelatedToUser()
中将状态更新为COMPLETED,而不是从
executeCronJob()

或者您可能希望
someOtherService.doSomeActionRelatedToUser(用户);
返回
CompletableFuture
,然后更新状态


希望有帮助。

这就是问题所在。我需要多个线程来访问给定的代码块,以便每个线程可以在不同的用户上工作。同步问题不应该只在访问同一个用户实例时出现吗?您可以只同步我评论中提到的代码块。这将确保findFirstNotInProgress用户没有被多个线程同时读取。doSomeActionRelatedToUser方法仍然可以被多个线程访问这就是问题所在。我需要多个线程来访问给定的代码块,以便每个线程可以在不同的用户上工作。同步问题不应该只在访问sam时发生吗用户实例?您只能同步我的评论中提到的代码块。这将确保findFirstNotInProgress用户不会被多个线程同时读取。doSomeActionRelatedToUser方法仍然可以被多个线程访问,例如多个线程尝试更新同一实体,一个线程成功,当下一个线程开始提交数据时,它会看到数据已被修改并最终抛出错误。看起来有多个线程试图更新同一实体,一个线程成功,当下一个线程开始提交数据时,它会看到数据已被修改并最终抛出错误。