简体   繁体   English

Hibernate忽略fetchgraph

[英]Hibernate ignores fetchgraph

This is my entity: 这是我的实体:

public class PersonItem implements Serializable{
    @Id
    @Column(name="col1")
    private String guid;

    @Column(name="col2")
    private String name;

    @Column(name="col3")
    private String surname;

    @Column(name="col4")
    private Date birthDate;
 //+getters and setters
}

This is how I get the list of persons: 这是我获得人员名单的方式:

Query query = em.createQuery("Select p from PersonItem p WHERE p.guid IN (:guids)");
EntityGraph<PersonItem> eg = em.createEntityGraph(PersonItem.class);
eg.addAttributeNodes("guid");
eg.addAttributeNodes("name");
eg.addAttributeNodes("surname");
query.setHint("javax.persistence.fetchgraph", eg);
query.setParameter("guids", guids);
List<PersonItem> list=query.getResultList();
em.close();
// And now I iterate result AFTER EM CLOSE
....iterate

If I understand fetch graph correcly it must load only those fields, which I specified. 如果我正确理解提取图,则它必须仅加载我指定的那些字段。 However, the field "birthDate" is also loaded. 但是,字段“ birthDate”也已加载。 Besides I see that in hibernate sql query 4 columns are selected. 此外,我看到在休眠SQL查询中选择了4列。

How to fix it? 如何解决? I use hibernate 5.1.0 as JPA provider. 我使用hibernate 5.1.0作为JPA提供程序。

Entity graphs are meant to control which relationships (eg one-to-one, one-to-many, etc.) are loaded lazily or eagerly. 实体图旨在控制延迟或渴望加载哪些关系(例如,一对一,一对多等)。 They may not work for loading individual columns (it depends on the provider). 它们可能不适用于加载各个列(取决于提供程序)。

Hibernate has some support for this, but it is fairly difficult to get working, described here . Hibernate有一些这方面的支持,但它是相当难以得到工作,描述在这里 However, they mention the following reticence towards this approach (which I whole-heartedly agree with): 但是,他们提到对这种方法的以下态度(我全心全意地同意):

Please note that this is mostly a marketing feature; 请注意,这主要是一种营销功能; optimizing row reads is much more important than optimization of column reads. 优化行读取比优化列读取重要得多。

So I would not recommend going too far down this road until you've confirmed that this is indeed a bottleneck in your application (eg this kind of fetch tuning can be a symptom of premature optimization). 因此,在您确认这确实是应用程序的瓶颈之前,我不建议您走得太远(例如,这种获取调整可能是过早优化的征兆)。

UPDATE: 更新:

As pointed out, JPA does leave it up to the provider as to whether or not simple columns (non-associations) are lazily fetched. 如前所述,JPA确实将是否懒惰地获取简单列(非关联)留给了提供者。

The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. EAGER策略是对持久性提供程序运行时的要求,必须热切地获取数据。 The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. LAZY策略向持久性提供程序运行时提供了提示,即首次访问数据时应延迟获取数据。 The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified. 该实现被允许急切地获取已为其指定LAZY策略提示的数据。 In particular, lazy fetching might only be available for Basic mappings for which property-based access is used. 特别是,懒惰获取可能仅适用于使用基于属性的访问的基本映射。

Starting with Hibernate 5, official support for bytecode enhancement was added and this may allow for lazy attribute fetching. 从Hibernate 5开始,增加了对字节码增强的官方支持,这可能允许懒惰的属性获取。

From the latest Hibernate docs we have: 最新的Hibernate文档中,我们可以得到:

2.3.2 2.3.2

fetch - FetchType (defaults to EAGER) fetch-FetchType(默认为EAGER)

Defines whether this attribute should be fetched eagerly or lazily. 定义该属性是应立即获取还是应延迟获取。 JPA says that EAGER is a requirement to the provider (Hibernate) that the value should be fetched when the owner is fetched, while LAZY is merely a hint that the value be fetched when the attribute is accessed. JPA说,EAGER是提供程序(休眠)的一项要求,即在提取所有者时应提取值,而LAZY只是提示在访问属性时要提取值。 Hibernate ignores this setting for basic types unless you are using bytecode enhancement. 除非您使用字节码增强功能,否则Hibernate对于基本类型将忽略此设置。

And this next snippet that describes the advantages of bytecode enhancement. 下一个片段描述了字节码增强的优点。

Lazy attribute loading 延迟属性加载

Think of this as partial loading support. 将其视为部分加载支持。 Essentially you can tell Hibernate that only part(s) of an entity should be loaded upon fetching from the database and when the other part(s) should be loaded as well. 从本质上讲,您可以告诉Hibernate在从数据库中获取时仅应加载实体的一部分,以及何时应加载其他部分。 Note that this is very much different from proxy-based idea of lazy loading which is entity-centric where the entity's state is loaded at once as needed. 请注意,这与基于代理的延迟加载思想非常不同,后者以实体为中心,在这种情况下,根据需要立即加载实体的状态。 With bytecode enhancement, individual attributes or groups of attributes are loaded as needed. 通过字节码增强,可以根据需要加载单个属性或属性组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM