【问题标题】:JPA Criteria OR condition on related entity with path navigation具有路径导航的相关实体上的 JPA 标准或条件
【发布时间】:2018-09-28 04:28:37
【问题描述】:

我有以下实体结构

public class Application {
    @JoinColumn(name = "account_id")
    @ManyToOne
    private Account account;

    @JoinColumn(name = "involved_account_id")
    @ManyToOne
    private Account involvedAccount;
}

public class Account {
    private string id;
    private string name;
}

我想获取account 名称或involvedAccount 名称与给定帐户名称匹配的所有应用程序。

CriteriaQuery<Application> query = cb.createQuery(Application.class);
Root<Application> root = query.from(Application.class);

Predicate conditions = cb.conjunction();

conditions = cb.and(conditions, cb.or(
    cb.like(
        cb.upper(root.get("account").get("name")), 
        accountName.toUpperCase()
    ), cb.like(
        cb.upper(root.get("involvedAccount").get("name")), 
        accountName.toUpperCase())
    )
);

query.where(conditions);
query.select(root);

但上面会产生以下 where 条件,它使用 and 作为主键而不是 or

where applicati0_.account_id=account1_.id
    and applicati0_.involved_account_id=account2_.id
    and 1=1
    and (
        upper(account1_.name) like ?
        or upper(account2_.id) like ?
    )

这是条件作为表达式失败的地方 applicati0_.account_id=account1_.id and applicati0_.involved_account_id=account2_.id 使用 and 而不是 or

【问题讨论】:

  • 你使用了@JoinColumn,这就是为什么添加了2个and条件。你能发布你的整个查询吗?另外,你能指定你的预期输出吗?
  • 我希望它是 or 而不是 and。即applicati0_.account_id=account1_.id or applicati0_.involved_account_id=account2_.id
  • SQL 查询正确。您希望 account1 是应用程序的帐户,而 account2 是应用程序的相关帐户。并且您希望 account1 的名称或 account2 的名称与给定的字符串一样。
  • 那么你不应该使用内连接(即 root.get("account")),而应该使用左连接。我强烈建议您使用 JPQL 查询而不是条件查询。会清楚很多。条件查询适用于动态查询,而不是静态查询。
  • 对不起。编辑@JBNizet

标签: hibernate jpa criteria-api


【解决方案1】:

按照 cmets 中的建议,使用 join

我现在无法测试,但这样的东西应该可以工作:

CriteriaQuery<Application> query = cb.createQuery(Application.class);
Root<Application> root = query.from(Application.class);
Join<Application, Account> account = root.join("account");
Join<Application, Account> involvedAccount = root.join("involvedAccount");

Predicate conditions = cb.conjunction();

conditions = cb.and(conditions, cb.or(
    cb.like(
        cb.upper(account.get("name")), 
        accountName.toUpperCase()
    ), cb.like(
        cb.upper(involvedAccount.get("name")), 
        accountName.toUpperCase())
    )
);

query.where(conditions);
query.select(root);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 2022-11-29
    • 2016-05-02
    • 1970-01-01
    • 2022-07-29
    • 2015-02-06
    • 2016-08-24
    相关资源
    最近更新 更多