了解spring-data如何处理@EntityGraph

Arn*_*lle 12 java hibernate spring-data

(我为这个问题做了一个SSCCE.)

我有2个简单的实体:EmployeeCompany.与默认获取策略(渴望)Employee@ManyToOne关系Company.

我希望能够EmployeeCompany不更改的情况下加载the 而不更改在中定义的获取策略,Employee因为我只需要为一个用例执行此操作.

JPA的实体图似乎是为了这个目的.

所以我@NamedEntityGraph在课堂上定义了一个Employee:

@Entity
@NamedEntityGraph(name = "employeeOnly")
public class Employee {

  @Id
  private Integer id;
  private String name;
  private String surname;
  @ManyToOne
  private Company company;

  //Getters & Setters
Run Code Online (Sandbox Code Playgroud)

EmployeeRepository这样的:

public interface EmployeeRepository extends CrudRepository<Employee, Integer> {

  @EntityGraph(value = "employeeOnly", type = EntityGraph.EntityGraphType.FETCH)
  List<Employee> findByCompanyId(Integer companyId);

}
Run Code Online (Sandbox Code Playgroud)

尽管使用了@EntityGraph,我可以在日志中看到Company仍然由hibernate加载:

2016-11-07 23:16:08.738 DEBUG 1029 --- [nio-8080-exec-2] org.hibernate.SQL                        : select employee0_.id as id1_1_, employee0_.company_id as company_4_1_, employee0_.name as name2_1_, employee0_.surname as surname3_1_ from employee employee0_ left outer join company company1_ on employee0_.company_id=company1_.id where company1_.id=?
2016-11-07 23:16:08.744 DEBUG 1029 --- [nio-8080-exec-2] org.hibernate.SQL                        : select company0_.id as id1_0_0_, company0_.name as name2_0_0_ from company company0_ where company0_.id=?
Run Code Online (Sandbox Code Playgroud)

为什么?怎么避免呢?

Dra*_*vic 9

目前,即使使用实体图,Hibernate也不支持将非惰性属性视为惰性.有一个未解决的问题:HHH-8776.

因此,目前唯一的解决方案是使关联变得懒惰.


xsa*_*ter 5

修改答案

per-说明书,取指类型@ManyToOneEAGER默认。但即使通过我们设置:

@ManyToOne(fetch = FetchType.LAZY)
private Company company;
Run Code Online (Sandbox Code Playgroud)

你会得到同样的结果。问题在于 spring-data-jpa 为您创建 HQL/JPQL 的方式。所以添加@ManyToOne(fetch = FetchType.LAZY) 不会工作是不足够的。要解决此问题,请在您的存储库中使用@ManyToOne(fetch = FetchType.LAZY) @Query注释:

员工.java :

@ManyToOne(fetch = FetchType.LAZY)
private Company company;
Run Code Online (Sandbox Code Playgroud)

EmployeeRepository.java

@Query("from Employee e where e.company.id = :companyId")
List<Employee> findByCompanyIdUsingQuery(@Param("companyId") Integer companyId);
Run Code Online (Sandbox Code Playgroud)

在测试中,这是您生成的SQL loadByCompanyId()(即生成左外连接):

select employee0_.id as id1_1_, employee0_.company_id as company_4_1_, employee0_.name as name2_1_, employee0_.surname as surname3_1_ from employee employee0_ left outer join company company1_ on employee0_.company_id=company1_.id where company1_.id=?
Run Code Online (Sandbox Code Playgroud)

这是使用@Query注释的方法生成的 SQL :

select employee0_.id as id1_1_, employee0_.company_id as company_4_1_, employee0_.name as name2_1_, employee0_.surname as surname3_1_ from employee employee0_ where employee0_.company_id=?
Run Code Online (Sandbox Code Playgroud)

您可以查看我的存储库中的最新代码。

哈。