如何减少ManyToOne(jpa/hibernate)的查询数量

ade*_*ood 6 hibernate jpa spring-data-jpa

我正在将 spring data jpa 与遗留数据库模式一起使用,并且在映射关系之一时遇到一些问题。数据库中有 2 个实体buyeremployee。一名员工可以有多个买家,因此这是ManyToOne买家与员工的关系。

这就是我配置 jpa/hibernate 实体的方式:

@Entity
@Table(name = "BUYER")
public class BuyerEntity {
   @Id
   @Column(name = "BUYER")
   private Long id;

   @ManyToOne
   @JoinColumn(name = "EMPLOYEE_ID")
   private EmployeeEntity employee;
....
Run Code Online (Sandbox Code Playgroud)

@Entity
@Table(name = "EMPLOYEE")
public class EmployeeEntity {

    @Id
    @Column(name = "EMPLOYEE_ID")
    private Long id;
....
Run Code Online (Sandbox Code Playgroud)

基本上,buyer表的外键Employee_Id指向表的主键employee

当我查找买家时,jpa/hibernate 首先执行查询以获取所有买家,然后对于每个买家,它运行另一个查询以检索相应的员工信息。这是非常低效的,因为我们可以通过在第一个查询中添加员工表列来轻松检索员工信息以及买家信息。

因此,不要首先执行如下所示的查询:

select buyer.id from buyer join employee ...
Run Code Online (Sandbox Code Playgroud)

然后对每个买家进行另一个查询:

select employee.* from employee where employee.id = ?
Run Code Online (Sandbox Code Playgroud)

如果我们可以建议 jpa/hibernate 执行这样的单个查询:

select buyer.*, employee.* from buyer join employee ...
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激。

Nar*_*ros 1

您应该能够发出以下查询来实现您的目标:

SELECT b FROM BuyerEntity b JOIN FETCH b.employee
Run Code Online (Sandbox Code Playgroud)

您会注意到,我在这里应用了一个JOIN FETCH,它告诉 Hibernate 不仅将EmployeeEntity表与BuyerEntity表连接起来,而且还将数据提取到关系中,作为对数据库的单个查询的一部分。

如果您想使用 JPA Criteria API

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<BuyerEntity> query = cb.createQuery( BuyerEntity.class );
Root<BuyerEntity> root = query.from( BuyerEntity.class );

// specify join-fetch
root.fetch( "employee", JoinType.INNER );
query.select( root );

List<BuyerEntity> results = entityManager.createQuery( query ).getResultList();
Run Code Online (Sandbox Code Playgroud)