JPA Criteria Disjunction

use*_*237 3 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'
Run Code Online (Sandbox Code Playgroud)

这给了我每一行key1 = 52540和objectCode等于Order AND的每一行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();
Run Code Online (Sandbox Code Playgroud)

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

我在这做错了什么?

谢谢你所有有用的答案:)

per*_*ssf 6

在这种情况下要做的第一件事是配置JPA提供程序以记录生成的查询.有关示例,请参阅此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));
Run Code Online (Sandbox Code Playgroud)

你的错误就是这样一条线:

builder.and(orderChangedLogBeans, builder.equal(from.get("key1"), orderId));
Run Code Online (Sandbox Code Playgroud)

不会修改到位orderChangedLogBeans.你必须得到CriteriaBuilder#和()返回的谓词:

orderChangedLogBeans = builder.and(orderChangedLogBeans, builder.equal(from.get("key1"), orderId));
Run Code Online (Sandbox Code Playgroud)