【问题标题】:JPA: How to fetch eagerly an embedded element collectionJPA:如何急切地获取嵌入式元素集合
【发布时间】:2016-02-19 18:38:31
【问题描述】:

考虑以下模型

@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
 }

Address 类使用@Embeddable 注释进行注释,Employee 类具有addresses 的嵌入元素集合。元素集合的fetch 设置为FetchType.LAZY。现在,我想创建一个@NamedQuery,它会检索所有具有热切初始化地址的员工。知道基于 JPA 2.1 的 JOIN FETCH will only work with entity collections 使用 @OneToMany@ManyToMany 注释,我将如何创建一个有效的 JPQL 查询,让我能够急切地检索嵌入的元素集合?

【问题讨论】:

  • 您如何得出join fetch 仅适用于实体的结论?你试过了吗?
  • @DraganBozanovic:根据文档,“FETCH JOIN 子句右侧引用的关联必须是属于作为查询结果返回的实体的关联。它是不允许为 FETCH JOIN 子句右侧引用的实体指定标识变量,因此对隐式获取的实体的引用不能出现在查询的其他地方。"
  • 集合值路径必须解析为关联字段
  • 好的,你试过了吗? :)
  • “集合值路径必须解析为关联字段。”为什么您认为嵌入式集合不被视为关联字段?无论如何,[left] join fetch 是 JPQL 中唯一为此目的而存在的东西,如果这能回答您的问题。

标签: java hibernate jpa jpql


【解决方案1】:

顺便说一句,更有效的方法可能是使用join,而是subselect

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

它进行了两次选择,而不是一次,但不会产生太多歧义。

【讨论】:

    【解决方案2】:

    在 JPA 2.1 规范 (JSR 338) 中,我找不到任何提示 fetch joins 仅适用于实体关系(但不适用于嵌入)。 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 查询:

    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 查询似乎解决了你的问题。

    【讨论】:

      猜你喜欢
      • 2012-12-17
      • 2021-02-17
      • 2013-07-28
      • 2011-06-24
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多