java - 按具有重叠路径表达式的 JPA 条件查询过滤

标签 java hibernate jpa criteria-api

我正在使用 Jpa/Hibernate 在 Spring Boot 应用程序中访问 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 属于 Company (id: 1)

  • Customer2 属于 Company2 (id: 2)

  • 公司 2 归公司 1 所有

  • 查询 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)

关于java - 按具有重叠路径表达式的 JPA 条件查询过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49853808/

相关文章:

java - HQL更新问题

java - 为什么我无法访问 android.widget 包中的包私有(private)字段?

java - Destinationsource.getQueues 不使用 SSL 连接返回正确数量的队列

java - 可以直接实例化hibernate session Factory但不能通过spring来实例化

java - Hibernate:如何为枚举类型的列指定@ColumnDefault

mysql - Ejb3.1 中的 setFirstResult() 和限制失败

java - 使用 QueryDSL JPA 在 MySQL 中查找重复的行

java - 批量插入中的 Postgres 错误 : relation "hibernate_sequence" does not exist position 17

java - 从 Java 迁移到 C++ API

java - 使用数组添加、查看、更新和删除学生记录