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

时间:2017-02-01 09:17:06

标签: java hibernate jpa

假设我有条件的查询,我需要锁定结果:

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();
}

parentCarrier也可以是Carrier,具体取决于它们如何装载到卡车上,例如盒子(如果他们直接装载则没有父母)和托盘上的盒子(为此托盘将是父母)。如果标签没有父项或者它们所在的托盘,标签可以属于一个框。

如果我执行此查询,标签可能还没有正确的状态,这很好,因为我们不需要对标准不匹配的标签做任何事情。但是,如果发生这种情况,那么我会收到此错误:

  

FOR UPDATE无法应用于外连接的可空区域

我可以尝试事先计算标签,如果没有结果或者首先获得我们想要处理的分销商的运营商的标签列表但是想要避免执行2个查询,则不执行此查询。有没有其他方法可以解决这个问题。

谢谢!

1 个答案:

答案 0 :(得分:0)

解决方案似乎只是放置您需要先从中选择的表,然后再执行所有其他连接,对于问题中提到的情况,这样的查询有效:

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 ";