JPA标准查询语言中的Disjunction

4

我希望学习和了解JPA Criteria。目前我在SQL方面很有能力,在Hibernate Criteria和HQL方面也相对有一定的能力。

我正在尝试使用OR语句进行一个相对简单的选择操作。

在普通的SQL中,我的选择语句如下:

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

这个语句会返回所有 key1=52540 且 objectCode 等于 Order 的行,同时也会返回所有 key=48398 且 objectCode 等于 Package 的行。这正是我想要的。
因此,我试图使用 JPA criteria 进行操作(看起来非常复杂...),目前我最好的猜测是这样:
    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个回答

6
在这种情况下,首先要做的是配置JPA提供程序以记录生成的查询。请参见此问题/答案中的示例。
回答你的问题,我不确定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));

谢谢。简单美观,运行得很好。 - user829237

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接