使用 JPA 和 Hibernate 加入并获取一些属性而不是所有集合

Join and fetch just some properties not all the collection with JPA and Hibernate

正在考虑此查询:

 @Query("select c from Contact c "
         + " join fetch c.abonnements ab ")
 Set<Contact > findServiceNotifContactFtech();

如何在 join 子句中从集合 abonnements 中获取两个或一个 属性 因为 fetch c.abonnements hibernate fetch me all属性,我得到了 abonnements

类型的 30 个属性

使用 SELECT o.property1, o.property2 FROM EntityA o WHERE ....,结果将是 List<Object[2]>,其中数组内容将包含值。

您期待 select 来自联系人的名字,姓氏意味着

 @Query("select c.firstname,c.lastname from Contact c "
         + " join fetch c.abonnements ab ")
 Set<Contact > findServiceNotifContactFtech();

如果您觉得这真的值得,请参阅下文,但请注意关于它很少值得的评论。

https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html

19.1.7. Using lazy property fetching

Hibernate3 supports the lazy fetching of individual properties. This optimization technique is also known as fetch groups. Please note that this is mostly a marketing feature; optimizing row reads is much more important than optimization of column reads. However, only loading some properties of a class could be useful in extreme cases. For example, when legacy tables have hundreds of columns and the data model cannot be improved.

To enable lazy property loading, set the lazy attribute on your particular property mappings:

Lazy property loading requires buildtime bytecode instrumentation. If your persistent classes are not enhanced, Hibernate will ignore lazy property settings and return to immediate fetching.

A different way of avoiding unnecessary column reads, at least for read-only transactions, is to use the projection features of HQL or Criteria queries. This avoids the need for buildtime bytecode processing and is certainly a preferred solution.

You can force the usual eager fetching of properties using fetch all properties in HQL.

基本上,如文档中所述,可以启用延迟获取属性,但在 运行 时将被忽略,除非您在构建时有 'enhanced' 您的 类使用文档中引用的 Ant 任务。如果您的 类 未被检测,那么 属性 级别的延迟加载将被静默忽略。这符合 JPA 规范,该规范不强制要求支持个别属性的延迟加载:

http://download.oracle.com/otn-pub/jcp/persistence-2.0-fr-eval-oth-JSpec/persistence-2_0-final-spec.pdf?AuthParam=1423670601_31b0b4beeddadd49047c08d63a9ad933

见 11.1.16

The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified

如果您只想 select Abonnement 属性并将它们映射到 DTO(例如 MyDTO),您只需将查询颠倒过来:

@Query("select new my.package.MyDTO(c, ab.prop1, ab.prop2) from Abonnements a join a.contact c")
Set<MyDTO> findMyDTO();

MyDTO 是这样的:

public MyDTO {
    private final Contact contact;
    private final String prop1;
    private final String prop2;

    public MyDTO(Contact contact, String prop1, String prop2) {
        this.contact= contact;
        this.prop1 = prop1;
        this.prop2 = prop2;
    }

    //getters
}

唯一的问题是每个 Abonnnment 个子条目您将获得更多 Contact 个条目。

由于您希望投影符合 DTO 中所需的属性,我建议您给 blaze-persistence 实体视图一个机会。你的 DTO 看起来像这样:

@EntityView(Contact.class)
public interface MyDTO {

  @IdMapping
  Integer getId();

  // You can have any JPQL expression here
  @Mapping("firstname")
  String getFirstname();

  // property name is the default mapping
  String getLastname();

  Set<AbonnementDTO> getAbonnements();

}

@EntityView(Abonnement.class)
public interface AbonnementDTO {

  @IdMapping
  Integer getId();

  String getProp1();

}

使用网站是这样的

@Inject
EntityManager em;
@Inject
CriteriaBuilderFactory cbf;
@Inject
EntityViewManager evm;

public void test() {
  CriteriaBuilder<Contact> cb = cbf.create(em, Contact.class);
  List<ContactDTO> result = evm.applySetting(EntityViewSetting.create(ContactDTO.class), cb)
      .getResultList();
}