简体   繁体   English

当值可能为空时,在JPA查询中使用悲观锁

[英]Using pessimistic lock in a JPA query when values could be null

Assuming I have a query with a condition and I need to have the results locked: 假设我有一个条件查询,并且需要锁定结果:

public List<E> findTableRows(String distributor, String status) {
  String queryStr = "SELECT l "
                  + "FROM   Carrier child "
                  + "LEFT   JOIN child.parentCarrier parent, "
                  + "       Label l "
                  + "WHERE  (child.distributor = :distributor or parent.distributor = :distributor) "
                  + "AND    (child.label = l or parent.label = l) "
                  + "AND    l.status = :status ";

  Query q = entityManager.createQuery(queryStr);

  q.setParameter("distributor", distributor);
  q.setParameter("status", status);
  q.setLockMode(LockModeType.PESSIMISTIC_FORCE_INCREMENT);

  return q.getResultList();
}

The parentCarrier can also be a Carrier , depending on how they get loaded on a truck, for example boxes (which have no parent if they get loaded directly) and boxes on pallets (for which the pallets would be the parent). parentCarrier也可以是Carrier ,具体取决于它们在卡车上的装载方式,例如,箱子(如果直接装载则没有父箱)和货盘上的箱子(对于这些货盘,父箱)。 Labels can belong either to a box if it has no parent or to the pallet on which they reside. 如果标签没有父标签,它们可以属于一个盒子,也可以属于它们所在的托盘。

If I execute this query, there is a chance that the labels do not have the right status yet, which is fine, because we do not need to do anything with labels that don't match the criteria. 如果执行此查询,则标签可能没有正确的状态,这很好,因为我们不需要对不符合条件的标签进行任何操作。 However, if this happens, then I get this error: 但是,如果发生这种情况,则会出现此错误:

FOR UPDATE cannot be applied to the nullable side of an outer join FOR UPDATE不能应用于外部联接的可为空的一侧

I could try to count the labels beforehand and not execute this query if there are no results or first get a list of labels for the carriers of a distributor that we want to process, but would like to avoid executing 2 queries. 我可以尝试预先计算标签,如果没有结果,则不执行此查询,或者先获取要处理的分销商的承运商的标签列表,但又希望避免执行2个查询。 Is there any other way to solve this. 还有其他解决方法。

Thanks! 谢谢!

The solution seems to be simply putting the table you need to select from first and then do all the other joins later, for the case mentioned in the issue, a query like this works: 解决方案似乎只是简单地将您需要从中选择的表放在第一位,然后再进行所有其他联接,对于问题中提到的情况,类似这样的查询有效:

String queryStr = "SELECT l "
                + "FROM   Label l, "
                + "       Carrier child "
                + "LEFT   JOIN child.parentCarrier parent "
                + "WHERE  (child.distributor = :distributor or parent.distributor = :distributor) "
                + "AND    (child.label = l or parent.label = l) "
                + "AND    l.status = :status ";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM