用于读取的 JPA 锁定实体

Posted

技术标签:

【中文标题】用于读取的 JPA 锁定实体【英文标题】:JPA lock entity for reading 【发布时间】:2011-11-11 13:06:27 【问题描述】:

我有我的代码:

public static Computation findByDateAndPaymentSystem(EntityManager em, Calendar date, PaymentSystem paymentSystem) throws SCException 
        Query query = em.createNamedQuery("Computation.findByDateAndPaymentSystem");
        query.setParameter("date", date);
        query.setParameter("ps", paymentSystem);
        List<Computation> computationList = query.getResultList();
        if (computationList != null && computationList.size() > 0) 
            if (computationList.size() == 1) 
                return computationList.get(0);
             else 
                throw new SCException("Not unique result in computation for date '"
                        + new SimpleDateFormat("dd.MM.yyyy").format(new Date(date.getTimeInMillis())) + "' and paymentSystem = '"
                        + paymentSystem.getShortName() + "'");
            
         else 
            Computation computation = new Computation();
            computation.setDate(date);
            computation.setComputationState(ComputationState.CREATED);
            computation.setPaymentSystem(paymentSystem);
            em.persist(computation);
            return computation;
        
    

主要想法是每个日期和支付系统应该有一个计算实例。 但是如果在两个不同的事务中调用这个方法,那么可能的下一个场景: 第一次事务检查,如果该日期没有计算并创建计算但仍未提交创建的计算,另一个事务检查并创建计算,则两个事务都提交。因此,每个日期将有两次计算。

如何预防?

【问题讨论】:

如果数据和支付系统的组合是您数据库中的唯一约束,那么您将永远无法插入重复计算 可以参考***.com/questions/7839069/… 对实体进行悲观锁定。 【参考方案1】:

Computation.datePaymentSystem 组合应该是唯一的(约束),然后第二次插入将失败,或者您可以尝试合并多个条目(如果找到它们)。解决方案取决于您的用例和交易策略和设置。

【讨论】:

有没有办法在 JPA 中对两个字段创建唯一约束。这是必需的,因为我从 JPA 实体生成 db 的 shema。

以上是关于用于读取的 JPA 锁定实体的主要内容,如果未能解决你的问题,请参考以下文章

JPA 和乐观锁定模式

Spring data jpa 插入多个表以避免锁定表

使用 JPA / Hibernate 在无状态应用程序中进行乐观锁定

选择从 JPA 级别锁定的更新跳过

实体框架事务锁定

锁定 SQL Server 表以进行写入但不用于读取 [重复]