更新并返回spring数据JPA中的数据

时间:2016-04-07 15:35:19

标签: java spring hibernate spring-data spring-data-jpa

出于并发目的,我需要在从AVAILABLE池中进行选择时将数据库列的状态更新为USED。

我正在考虑尝试@Modifying@Query(根据where子句更新状态的查询)

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

因此,在spring数据中是否有可能更新并返回一行,以便首先读取该行的人可以专门使用它。

我的更新查询类似于UPDATE MyObject o SET o.state = 'USED' WHERE o.id = (select min(id) from MyObject a where a.state='AVAILABLE'),因此基本上会将最低可用ID标记为已使用。有一个锁定选项,但这些需要特殊处理,如果另一个线程发生异常,请再试一次,这在我的场景中未获批准

2 个答案:

答案 0 :(得分:1)

您需要显式声明一个事务,以避免其他事务能够读取所涉及的值,直到它提交为止。允许它的level with best performance READ_COMMITED ,它不允许来自其他事务的脏读(适合您的情况)。所以代码看起来像这样:

<强>回购:

@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;
}

答案 1 :(得分:1)

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

在第一个事务中加载实体,将其标记为USED,关闭事务。

这将刷新并提交更改,并确保在此期间没有其他人触摸实体。

在第二笔交易中,您无法对实体执行任何操作。

对于这些小额交易,我发现将它们移至单独的方法很笨拙,因此我可以使用@Transactional。因此,我改用TransactionTemplate