JPA Criteria Disjunction

时间:2013-01-18 10:56:28

标签: hibernate jpa criteria criteria-api

我正在努力学习和理解JPA标准。 到目前为止,我在SQL方面非常有能力,并且在Hibernate Criteria和HQL方面非常有能力。

我正在尝试使用OR语句进行相当简单的选择。

在普通SQL中,我的选择如下所示:

SELECT * FROM CHANGED_LOG
WHERE key1 = 52540 AND objectCode = 'Order'
OR key1 = 48398 AND objectCode = 'Package'

这给了我keyone = 52540和objectCode等于Order的每一行 以及key = 48398和objectCode等于Package的每一行。 这正是我想要的。

因此尝试使用JPA标准(这看起来格外复杂......),到目前为止,我最好的猜测是:

    CriteriaBuilder builder = entityManager.getCriteriaBuilder();

    CriteriaQuery<ChangedLogBean> query = builder.createQuery(ChangedLogBean.class);
    Root<ChangedLogBean> from = query.from(ChangedLogBean.class);
    CriteriaQuery<ChangedLogBean> select = query.select(from);

    Predicate orderChangedLogBeans = builder.conjunction();
    builder.and(orderChangedLogBeans, builder.equal(from.get("key1"), orderId));
    builder.and(orderChangedLogBeans, builder.equal(from.get("objectCode"), ChangedLogBean.ObjectType.OrderBean));

    Predicate packageChangedLogBeans = builder.conjunction();
    builder.and(packageChangedLogBeans, builder.equal(from.get("key1"), packageId));
    builder.and(packageChangedLogBeans, builder.equal(from.get("objectCode"), ChangedLogBean.ObjectType.PackageBean));

    Predicate orderOrPackage = builder.disjunction();
    orderOrPackage.getExpressions().add(orderChangedLogBeans);
    orderOrPackage.getExpressions().add(packageChangedLogBeans);

    query.where(orderOrPackage);

    return entityManager.createQuery(select).getResultList();

哇。一个简单查询的很多行...但是,这仍然从数据库向我回到了每一行。

我在这里做错了什么?

感谢您提供的所有有用答案:)

1 个答案:

答案 0 :(得分:6)

在这种情况下要做的第一件事是配置JPA提供程序以记录生成的查询。有关示例,请参阅this q/a

要回答你的问题,我不确定getExpressions()的用法,所以我建议采用以下粗鲁的方法:

Predicate p1 = builder.equal(...);
Predicate p2 = builder.equal(...);
Predicate p3 = builder.equal(...);
Predicate p4 = builder.equal(...);

Predicate p5 = builder.and(p1, p2);
Predicate p6 = builder.and(p3, p4);

query.where(builder.or(p5, p6));

你的错误是这样的一行:

builder.and(orderChangedLogBeans, builder.equal(from.get("key1"), orderId));

不会就地orderChangedLogBeans进行修改。你必须得到CriteriaBuilder#and()返回的谓词:

orderChangedLogBeans = builder.and(orderChangedLogBeans, builder.equal(from.get("key1"), orderId));