Spring数据JPA原生查询跳过锁定

时间:2017-09-14 00:27:27

标签: spring hibernate jpa spring-data-jpa

我想使用Spring Data JPA对Oracle执行SKIP LOCKED查询,所以我尝试了以下内容:

@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query(value = "SELECT * FROM User WHERE ID=?1 FOR UPDATE SKIP LOCKED", nativeQuery = true)
User findOne(UUID id);

我尝试了上述操作,发现生成的查询包含FOR UPDATE,但不包含SKIP LOCKED(以下是从日志生成的查询):

select ent0_.column1 as name, ent0_.CREATED_DATE as CREATED_2_33_0_ from TABLE_NAME alias_name where ent0_.column1=? for update

如果我从查询方法中删除@Lock,则生成的查询甚至没有FOR UPDATE

请根据需要建议我如何使用FOR UPDATE SKIP LOCKED生成查询。

2 个答案:

答案 0 :(得分:1)

添加:

  

@QueryHints({@ QueryHint(name =" javax.persistence.lock.timeout",value   =&#34 -2")})

答案 1 :(得分:0)

您可以将-2设置为超时值,以便在可能的情况下使用“跳过锁定”。

  

PESSIMISTIC_WRITE,javax.persistence.lock.timeout设置为-2

     

UPGRADE_SKIPLOCKED

     

锁定获取请求将跳过已经锁定的行。它使用   选择......在Oracle和PostgreSQL 9.5中进行更新跳过锁定,或者   在SQL Server中使用(行锁,上锁,readpast)进行选择...

public interface MyRepository extends CrudRepository<MyEntity, Long> {

    /**
     * The lock acquisition request skips the already locked rows.
     * It uses a SELECT …​ FOR UPDATE SKIP LOCKED in Oracle and PostgreSQL 9.5,
     * or SELECT …​ with (rowlock, updlock, readpast) in SQL Server.
     */
    String UPGRADE_SKIPLOCKED = "-2";

    @Lock(value = LockModeType.PESSIMISTIC_WRITE) // adds 'FOR UPDATE' statement
    @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = UPGRADE_SKIPLOCKED)})
    MyEntity findFirstByStatus(String status);

}

这样做,选择查询将具有select ... for update skip locked

https://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/chapters/locking/Locking.html