Java spring数据JPA中的更新和返回数据

Java spring数据JPA中的更新和返回数据,java,spring,hibernate,spring-data,spring-data-jpa,Java,Spring,Hibernate,Spring Data,Spring Data Jpa,出于并发性的目的,我需要在从可用池中进行选择时更新要使用的数据库列的状态 我想尝试@modify和@Queryquery根据where子句更新状态 这一切都很好,但这是一个更新查询,因此它不会返回更新的数据 那么,在spring数据中是否有可能更新并返回一行,以便首先读取该行的人可以独占使用该行 我的更新查询类似于updatemyobject o SET o.state='USED',其中o.id=select minid from MyObject a WHERE a.state='AVAIL

出于并发性的目的,我需要在从可用池中进行选择时更新要使用的数据库列的状态

我想尝试@modify和@Queryquery根据where子句更新状态

这一切都很好,但这是一个更新查询,因此它不会返回更新的数据

那么,在spring数据中是否有可能更新并返回一行,以便首先读取该行的人可以独占使用该行


我的更新查询类似于updatemyobject o SET o.state='USED',其中o.id=select minid from MyObject a WHERE a.state='AVAILABLE',因此基本上最低的可用id将被标记为USED。有一个锁定选项,但这些需要异常处理,如果另一个线程发生异常,请重试,这在我的场景中是不允许的

您需要显式声明事务,以避免其他事务在提交之前能够读取所涉及的值。允许它是READ_committed,它不允许来自其他事务的脏读适合您的情况。因此,代码将如下所示:

回购:


我建议使用多个事务加上乐观锁定。 确保您的实体具有带有@Version注释的属性

在第一个事务中,加载实体,将其标记为已使用,关闭事务

这将刷新并提交更改,同时确保没有其他人接触该实体

在第二个事务中,您不能对实体执行任何您想执行的操作


对于这些小事务,我发现将它们移动到单独的方法中,以便使用@Transactional是很笨拙的。因此,我改用TransactionTemplate。

Hi,当我知道id但不知道id时,您的解决方案将起作用。我的更新查询类似于update MyObject o SET o.state='USED'其中o.id=从MyObject a中选择minid,其中a.state='AVAILABLE',因此基本上最低可用id将被标记为USED。有一个锁定选项,但这些需要异常处理,如果另一个线程发生异常,请重试,这在我的场景中不被批准。只编辑了我的答案。继续执行单个Spring事务,它将实现您想要的。无论如何,如果您的问题更新为您在上述评论中提供的详细信息,那将是一件好事。它应该可以在多台服务器上工作,因此事务性解决方案不是一个解决方案。最后,我可能不得不使用乐观锁定和悲观锁定,但只有在没有其他选择的情况下才会这样做。“它应该可以在多个服务器上工作,所以这不是一个解决方案。”。事实上,这取决于数据库供应商和体系结构。事务在数据库级别工作,因此集群数据库必须保证它们被正确隔离。请用您的全部要求编辑您的问题。在这种情况下,您仍然需要锁定和异常处理,因为您还需要如何防止并发请求访问同一行…有关标题中的问题,请参阅:
@Repository
public interface MyObjectRepository extends JpaRepository<MyObject, Long> {

    @Modifying
    @Query("UPDATE MyObject o SET o.state = 'USED' WHERE o.id = :id")
    void lockObject(@Param("id") long id);

    @Query("select min(id) from MyObject a where a.state='AVAILABLE'")
    Integer minId();
}
@Transactional(isolation=Isolation.READ_COMMITTED)
public MyObject findFirstAvailable(){
    Integer minId;
    if ((minId = repo.minId()) != null){
        repo.lockObject(minId);
        return repo.findOne(minId);
    }
    return null;
}