有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring数据Jpa@Lock注释带有@Transactional

根据@Lock注释的java文档:

Annotation used to specify the LockModeType to be used when executing the query. It will be evaluated when using Query on a query method or if you derive the query from the method name.

如上所述,将使用@Query annotation或findBySomething对其进行评估。。()方法

但根据我的发现,当我将@Lock注释和@Transactional放在任何方法中,并在该事务方法中从db获取记录时,它正在获取db行上的锁,理想情况下它不应该(如果我错了,请纠正我):

我用两个事务T1和T2对此进行了验证,如下所示:

  1. 首先启动T1,并从数据库中获取一些记录,然后休眠该线程,但不更新它们

  2. 现在,在另一个具有相同@Lock和悲观写入和@Transactional注释的方法上启动T2,获取相同的记录并尝试更新它们,但当它尝试提交这些更改时,它会等待一段时间,然后抛出异常,称为PessimsticLock timeout exception

@Transactional
@Lock(LockModeType.PESSIMISTIC_WRITE)
public boolean addInventory(Integer id){

   repo.findById(id)// #statement 1
}

此外,当调用#语句1时,它不会触发“select for update”查询,而只触发select查询

@Lock是否可以与@Transactional一起使用,并且在此事务下获取的所有行都可以获得锁

使用SpringBoot版本2.1.4。释放


共 (1) 个答案

  1. # 1 楼答案

    我能够理解我所面临的行为:

    @Lock annotation无效,如果它将方法置于仅具有@Transactional annotation的状态,则它正在使用@Query或findByXyz()方法

    在我的例子中,T2事务无法提交,因为数据库是MySQL,具有默认事务隔离级别“Repeatable Read”,在T1提交之前不允许继续T2事务

    @Lock(LockModeType.PESSIMISTIC_WRITE) //will not have any effect
    @Transactional
    public Response handleRequest(){
      //no lock will acquire
    // prior to know about mysql's repeatble read, i was having impression, any call to db in this method will lock the db rows, which is wrong
    }
    
    
    @Lock(LockModeType.PESSIMISTIC_WRITE)// will fire select for update
    @Transactional
    public findByUserId(){
    
    // any db call from repo layer which have no lock annotations 
    
    }
    @Lock(LockModeType.PESSIMISTIC_WRITE)// will fire select for update
    @Query("select u from user as u where u.id=:id")
    @Transactional
    public getByUserID(String id){
    
    }