按具有重叠路径表达式的 JPA 条件查询过滤
Filter by JPA Criteria Query with overlapping paths expressions
我正在使用 Jpa/Hibernate 在 Spring 引导应用程序中访问 MariaDB
我有一个客户及其公司的模型。一家公司可以归另一家公司所有。
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
class customer {
@Id
private Long id;
private String name;
private Company company;
}
class Company {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ownedBy")
private Company ownedBy;
}
我想筛选公司的所有客户和公司拥有的公司的客户。
例如
Customer1 属于公司 (id: 1)
Customer2 属于 Company2 (id: 2
Company2 归 Company1 所有
查询 id = 1 -> [Customer1, Customer2]
我构建了以下 2 个预测来通过公司 ID 或拥有的公司 ID 匹配客户。
Join join = root.join("company");
Path companyPath = join.get("id");
// creating this path lead to the other one not working any more
Path companyOwnedPath = join.join("ownedBy").get("id");
Predicate company = criteriaBuilder.equal(companyPath, id);
Predicate companyOwned = criteriaBuilder.equal(companyOwnedPath, id);
它们都是单独工作的,所以我尝试将它们与 or 组合起来。
criteriaBuilder.or(company, companyOwned);
但后来我只得到匹配 companyOwned
的结果。但是我发现总是在我声明 companyOwnedPath
时(即使没有谓词),company
谓词不再起作用。
创建这样的路径有副作用吗?
这是整个查询构建的代码。
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.transaction.annotation.Transactional;
public interface CustomerRepositoryCustom {
List<Customer> getByCompany(Long id, int page, int size);
}
@Transactional(readOnly = true)
public class CustomerRepositoryImpl implements CustomerRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public List<Customer> getByCompany(Long id, int page, int size) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Customer> query = criteriaBuilder.createQuery(Customer.class);
Root<Customer> root = query.from(Customer.class);
CriteriaQuery<Customer> select = query.select(root);
query.where(buildCompanyPredicate(criteriaBuilder, root, id);
TypedQuery<Customer> typedQuery = entityManager.createQuery(select);
typedQuery.setFirstResult(page * size);
typedQuery.setMaxResults(page);
return typedQuery.getResultList();
}
private Predicate buildCompanyPredicate(CriteriaBuilder criteriaBuilder, Root root, Long id) {
// company join
Join join = root.join("company");
Path companyPath = join.get("id");
// creating this path lead to the other one not working any more
Path companyOwnedPath = join.join("ownedBy").get("id");
Predicate company = criteriaBuilder.equal(companyPath, id);
Predicate companyOwned = criteriaBuilder.equal(companyOwnedPath, id);
return criteriaBuilder.or(company, companyOwned);
}
}
谢谢
From.join()
方法系列的默认连接类型是 INNER JOIN
,这意味着,如果一家公司不属于另一家公司,则它不会出现在结果中。你想要join.join("ownedBy", JoinType.LEFT)
。
我正在使用 Jpa/Hibernate 在 Spring 引导应用程序中访问 MariaDB
我有一个客户及其公司的模型。一家公司可以归另一家公司所有。
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
class customer {
@Id
private Long id;
private String name;
private Company company;
}
class Company {
@Id
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ownedBy")
private Company ownedBy;
}
我想筛选公司的所有客户和公司拥有的公司的客户。
例如
Customer1 属于公司 (id: 1)
Customer2 属于 Company2 (id: 2
Company2 归 Company1 所有
查询 id = 1 -> [Customer1, Customer2]
我构建了以下 2 个预测来通过公司 ID 或拥有的公司 ID 匹配客户。
Join join = root.join("company");
Path companyPath = join.get("id");
// creating this path lead to the other one not working any more
Path companyOwnedPath = join.join("ownedBy").get("id");
Predicate company = criteriaBuilder.equal(companyPath, id);
Predicate companyOwned = criteriaBuilder.equal(companyOwnedPath, id);
它们都是单独工作的,所以我尝试将它们与 or 组合起来。
criteriaBuilder.or(company, companyOwned);
但后来我只得到匹配 companyOwned
的结果。但是我发现总是在我声明 companyOwnedPath
时(即使没有谓词),company
谓词不再起作用。
创建这样的路径有副作用吗?
这是整个查询构建的代码。
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.transaction.annotation.Transactional;
public interface CustomerRepositoryCustom {
List<Customer> getByCompany(Long id, int page, int size);
}
@Transactional(readOnly = true)
public class CustomerRepositoryImpl implements CustomerRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public List<Customer> getByCompany(Long id, int page, int size) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Customer> query = criteriaBuilder.createQuery(Customer.class);
Root<Customer> root = query.from(Customer.class);
CriteriaQuery<Customer> select = query.select(root);
query.where(buildCompanyPredicate(criteriaBuilder, root, id);
TypedQuery<Customer> typedQuery = entityManager.createQuery(select);
typedQuery.setFirstResult(page * size);
typedQuery.setMaxResults(page);
return typedQuery.getResultList();
}
private Predicate buildCompanyPredicate(CriteriaBuilder criteriaBuilder, Root root, Long id) {
// company join
Join join = root.join("company");
Path companyPath = join.get("id");
// creating this path lead to the other one not working any more
Path companyOwnedPath = join.join("ownedBy").get("id");
Predicate company = criteriaBuilder.equal(companyPath, id);
Predicate companyOwned = criteriaBuilder.equal(companyOwnedPath, id);
return criteriaBuilder.or(company, companyOwned);
}
}
谢谢
From.join()
方法系列的默认连接类型是 INNER JOIN
,这意味着,如果一家公司不属于另一家公司,则它不会出现在结果中。你想要join.join("ownedBy", JoinType.LEFT)
。