Hibernate Criteria Builder:如何按可为空的实体属性进行过滤?
Hibernate Criteria Builder: How to filter by a nullable entity attribute?
场景
我有一个实体 Treatment
,它有两个外键:
@ManyToOne
@JoinColumn(name = "product_id", nullable = true)
private Product product;
@ManyToOne
@JoinColumn(name = "product2_id", nullable = true)
private Product product2;
这个 Product
实体有一个常规的 id 属性作为 PK。
我想要的:
我想找到任何产品 ID 与给定 ID 匹配的所有治疗方法,在本机 SQL 中类似于:
select t.id, product_id,product2_id, p1.category_id,p2.category_id
from Treatment t
left join product p1 on t.product_id=p1.id
left join product p2 on t.product2_id=p2.id
where p1.category_id=17 or p2.category_id=17
到目前为止我做了什么:
鉴于:
CriteriaQuery<Treatment> cr = cb.createQuery(Treatment.class);
Root<Treatment> root = cr.from(Treatment.class);
我的尝试是:
if (category != null ) {
Predicate predicate = cb.or(
cb.equal(root.get("product").get("category"), category),
cb.equal(root.get("product2").get("category"), category)
);
predicateList.add(predicate);
}
但它没有用:它得到两种产品都不为空且至少其中一种符合类别条件的处理。
生成的查询是(清理后使其可读):
select
...
from treatment t
cross join product p1
cross join product p2
where t.product_id=p1.id
and t.product2_id=p2.id
and (p1.category_id=17 or p2.category_id=17)
order by t.id desc
这应该有效:
Predicate predicate = (root1, cq1, cb1) -> Specifications.where(
cb1.equal(root1.get("product").get("category"), category)).or(
cb1.equal(root1.get("product2").get("category"), category))
.toPredicate(root, cb, cq);
尝试使用 From#join
构建路径,您可以在其中明确定义连接类型,例如:
Predicate predicate = cb.or(
cb.equal(root.join("product", JoinType.LEFT).get("category"), category),
cb.equal(root.join("product2", JoinType.LEFT).get("category"), category)
);
场景
我有一个实体 Treatment
,它有两个外键:
@ManyToOne
@JoinColumn(name = "product_id", nullable = true)
private Product product;
@ManyToOne
@JoinColumn(name = "product2_id", nullable = true)
private Product product2;
这个 Product
实体有一个常规的 id 属性作为 PK。
我想要的:
我想找到任何产品 ID 与给定 ID 匹配的所有治疗方法,在本机 SQL 中类似于:
select t.id, product_id,product2_id, p1.category_id,p2.category_id
from Treatment t
left join product p1 on t.product_id=p1.id
left join product p2 on t.product2_id=p2.id
where p1.category_id=17 or p2.category_id=17
到目前为止我做了什么:
鉴于:
CriteriaQuery<Treatment> cr = cb.createQuery(Treatment.class);
Root<Treatment> root = cr.from(Treatment.class);
我的尝试是:
if (category != null ) {
Predicate predicate = cb.or(
cb.equal(root.get("product").get("category"), category),
cb.equal(root.get("product2").get("category"), category)
);
predicateList.add(predicate);
}
但它没有用:它得到两种产品都不为空且至少其中一种符合类别条件的处理。
生成的查询是(清理后使其可读):
select
...
from treatment t
cross join product p1
cross join product p2
where t.product_id=p1.id
and t.product2_id=p2.id
and (p1.category_id=17 or p2.category_id=17)
order by t.id desc
这应该有效:
Predicate predicate = (root1, cq1, cb1) -> Specifications.where(
cb1.equal(root1.get("product").get("category"), category)).or(
cb1.equal(root1.get("product2").get("category"), category))
.toPredicate(root, cb, cq);
尝试使用 From#join
构建路径,您可以在其中明确定义连接类型,例如:
Predicate predicate = cb.or(
cb.equal(root.join("product", JoinType.LEFT).get("category"), category),
cb.equal(root.join("product2", JoinType.LEFT).get("category"), category)
);