JPA:如何热切地获取嵌入式元素集合

2022-09-03 06:28:29

请考虑以下模型

@Entity
// JPA and JAXB annotations here
public class Employee implements Serializable {
     // other fields, annotations, stuffs
     ...
     @ElementCollection(fetch = FetchType.LAZY,
        targetClass = Address.class)
     @CollectionTable(name = "employee_address",
        schema = "hris",
        joinColumns = @JoinColumn(name = "employee_id",
                nullable = false,
                referencedColumnName = "employee_id",
                foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT)))
     protected Set<Address> addresses;
     // setters, getters
     ...
 }

 @Embeddable
 // JAXB annotations here
 public class Address implements Serializable {
      // fields, setters, getters
 }

该类使用批注进行批注,并且该类具有 嵌入的元素集合 。元素集合的 设置为 。现在,我想创建一个可以检索地址已热切初始化的所有员工。知道这仅适用于使用 JPA 2.1 注释或基于 JPA 2.1 的实体集合,我将如何创建一个有效的查询,使我能够热切地检索嵌入元素集合?Address@EmbeddableEmployeeaddressesfetchFetchType.LAZY@NamedQueryJOIN FETCH@OneToMany@ManyToManyJPQL


答案 1

在 JPA 2.1 规范 (JSR 338) 中,我找不到任何提示,表明获取联接仅适用于实体关系(而不是嵌入)。JSR 338 第 4.4.5.3 节甚至指出:

允许将获取关联或元素集合作为执行查询的副作用。FETCH JOIN

作为另一个提示,以下使用Hibernate 4.3.11作为JPA提供程序执行的最小示例(本质上类似于您的示例)将生成单个查询:

地址嵌入:

@Embeddable public class Address { private String city; }

员工实体:

@Entity public class Employee {

    @Id private Long id;

    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(name = "address", 
           joinColumns = @JoinColumn(name="employee_id"))
    private Set<Address> addresses;

}

JPQL Query:

em.createQuery("select e from Employee e join fetch e.addresses").getResultList();

生成的 SQL 查询:

select
    employee0_.id as id1_1_,
    addresses1_.employee_id as employee1_1_0__,
    addresses1_.city as city2_5_0__ 
from
    Employee employee0_ 
inner join
    address addresses1_ on employee0_.id=addresses1_.employee_id

因此,上面的JPQL查询似乎解决了您的问题。


答案 2

顺便说一句,更有效的方法可能不是使用连接,而是部分选择

@Fetch(FetchMode.SUBSELECT)
@BatchSize(size=500)

它做了两个选择,而不是一个,但不会产生太多的歧义。


推荐