【问题标题】:Spring Data Jpa @Lock annotation with @Transactional带有@Transactional的Spring Data Jpa @Lock注释
【发布时间】:2022-01-02 14:35:33
【问题描述】:

根据 @Lock 注释的 java 文档:

用于指定执行查询时要使用的 LockModeType 的注解。当对查询方法使用 Query 或从方法名称派生查询时,将对它进行评估。

如上所述,它将使用@Query 注释或 findBySomething..() 方法进行评估。

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

我用两个交易 T1 和 T2 验证了这一点,如下所示:

  1. 首先启动 T1,然后从 db 中获取一些记录并休眠该线程并且没有更新它们。

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

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

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

当#statement 1 被调用时,它不会触发“select for update”查询,而只会触发 select 查询。

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

使用 SpringBoot 2.1.4.RELEASE 版本

【问题讨论】:

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


    【解决方案1】:

    我能够弄清楚我所面临的行为:

    @Lock注解没有作用,如果它把只有@Transactional注解的方法放在上面,它正在使用@Query或者findByXyz()方法。

    在我的情况下,T2 事务无法提交,因为数据库是 MySQL 并且具有默认事务隔离级别“可重复读取”,在 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){
    
    }
    
    

    【讨论】:

      猜你喜欢
      • 2015-04-16
      • 1970-01-01
      • 2014-07-15
      • 2021-12-24
      • 2013-01-06
      • 2015-01-15
      • 2018-06-27
      • 1970-01-01
      • 2019-03-10
      相关资源
      最近更新 更多