【问题标题】:JPA 2 Criteria API: why is isNull being ignored when in conjunction with equal?JPA 2 Criteria API:为什么 isNull 在与 equal 结合使用时被忽略?
【发布时间】:2011-03-02 03:43:24
【问题描述】:

我有以下实体类(ID继承自PersistentObjectSupport类):

@Entity
public class AmbulanceDeactivation extends PersistentObjectSupport implements Serializable {
    private static final long serialVersionUID = 1L;

    @Temporal(TemporalType.DATE) @NotNull
    private Date beginDate;

    @Temporal(TemporalType.DATE)
    private Date endDate;

    @Size(max = 250)
    private String reason;

    @ManyToOne @NotNull
    private Ambulance ambulance;

    /* Get/set methods, etc. */
}

如果我使用 Criteria API 执行以下查询:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<AmbulanceDeactivation> cq = cb.createQuery(AmbulanceDeactivation.class);
Root<AmbulanceDeactivation> root = cq.from(AmbulanceDeactivation.class);
EntityType<AmbulanceDeactivation> model = root.getModel();
cq.where(cb.isNull(root.get(model.getSingularAttribute("endDate", Date.class))));
return em.createQuery(cq).getResultList();

我在日志中打印了以下 SQL:

FINE: SELECT ID, REASON, ENDDATE, UUID, BEGINDATE, VERSION, AMBULANCE_ID FROM AMBULANCEDEACTIVATION WHERE (ENDDATE IS NULL)

但是,如果我将之前代码中的 where() 行更改为这一行:

cq.where(cb.isNull(root.get(model.getSingularAttribute("endDate", Date.class))),
    cb.equal(root.get(model.getSingularAttribute("ambulance", Ambulance.class)), ambulance));

我得到以下 SQL:

FINE: SELECT ID, REASON, ENDDATE, UUID, BEGINDATE, VERSION, AMBULANCE_ID FROM AMBULANCEDEACTIVATION WHERE (AMBULANCE_ID = ?)

也就是说,isNull 标准被完全忽略。就好像它甚至不存在一样(如果我只提供与 where() 方法相同的标准,我会打印相同的 SQL)。

这是为什么呢?是错误还是我遗漏了什么?

【问题讨论】:

  • 顺便说一句,我有一个解决方法 - 使用 JPQL: em.createQuery("select d from AmbulanceDeactivation d where d.endDate is null and d.ambulance.id = " + ambulance.getId() ).getSingleResult();。我只想知道为什么 Criteria API 不起作用。

标签: java jpa criteria-api jpa-2.0


【解决方案1】:

我使用 EclipseLink 测试了您的代码和条件查询(您使用的是 EclipseLink,对吗?)并且我重现了该行为:isNull 部分被忽略了。

但是,使用 Hibernate Entity Manager 3.5.1,会生成以下查询:

select ambulanced0_.id as id7_, ambulanced0_.ambulance_id as ambulance5_7_, ambulanced0_.beginDate as beginDate7_, ambulanced0_.endDate as endDate7_, ambulanced0_.reason as reason7_ 
from AmbulanceDeactivation ambulanced0_ 
where (ambulanced0_.endDate is null) and ambulanced0_.ambulance_id=?

这是预期的结果。所以我想我们可以假设这是您的 JPA 2.0 提供程序的错误。

【讨论】:

  • 是的,我正在使用 EclipseLink(NetBeans + GlassFish v3 组合的默认提供程序)。感谢您的回复!我打算提交一个错误,但它似乎已经提交了:bugs.eclipse.org/bugs/show_bug.cgi?id=316144
  • @Vitor 实际上,这看起来是同一个问题。投票给它:)
【解决方案2】:

我在使用嵌入了 EclipseLink 2.0 的 Glassfish 3.0.1 时遇到了同样奇怪的行为。

我已尝试使用 Glassfish 3.1.2 中包含的 Eclipselink 2.3 库仔细更改嵌入式 eclipselink 库。它解决了这个问题。所以绝对可以肯定,相等条件下的 isNull 检查是使用 criteriaBuilder 的 eclipselink 错误。

我将尽快升级我们的 GlassFish 环境以消除该问题。

【讨论】:

    猜你喜欢
    • 2011-04-30
    • 1970-01-01
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    • 2021-11-06
    • 2019-03-22
    • 1970-01-01
    相关资源
    最近更新 更多