Hibernate忽略fetchgraph [英] Hibernate ignores fetchgraph

查看:106
本文介绍了Hibernate忽略fetchgraph的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的实体:

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

@Column(name =col2)
私人字符串名称;

@Column(name =col3)
private String surname;

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

这就是我如何获得人名列表:

 查询查询= em.createQuery(从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,例如);
query.setParameter(guids,guids);
列表< PersonItem>列表= query.getResultList();
em.close();
//现在迭代结果后EM CLOSE
....迭代

如果我正确理解提取图形,它只能加载我指定的那些字段。然而,字段birthDate也被加载。除此之外,我看到在休眠sql查询4列被选中。

如何解决它?我使用hibernate 5.1.0作为JPA provider。

解决方案

实体图旨在控制哪些关系(例如一对一,一对多等)都是懒洋洋地或热切地加载。它们可能无法用于加载单个列(它取决于提供者)。

Hibernate对此有一些支持,但要实现这一点相当困难,描述这里。然而,他们提到了对这种做法的沉默(我完全同意这一点):


请注意,这主要是一种营销特征;优化行
的读取比列读取的优化要重要得多。


所以我不会推荐这么做直到您确认这确实是您的应用程序的瓶颈(例如,这种获取调优可能是过早优化的一个症状)。

更新: p>

正如指出的那样,JPA确实让提供者决定是否简单列(非关联)被延迟取回。


EAGER策略是对持久性提供者
运行时的一个要求,即必须急切地提取数据。 LAZY策略对持久性提供者运行时是一个
的提示,即数据在第一次访问时应该被延迟地获取
。允许执行
以获取指定了LAZY策略提示
的数据。特别是,延迟提取可能只适用于使用基于属性的访问的
Basic映射。


Hibernate 5,增加了对字节码增强的官方支持,这可能允许延迟的属性获取。



latest hibernate docs 我们有:


2.3.2

fetch - FetchType(默认为EAGER)

定义是否这个属性应该被热切或懒洋洋地提取。
JPA表示EAGER是提供者(Hibernate)的一个要求,即在获取所有者时应该获取
的值,而LAZY是
仅仅是提示当属性是
访问。 Hibernate忽略基本类型的这个设置,除非你
正在使用字节码增强。

下面的代码段描述了字节码增强。


懒惰属性加载



将此视为部分加载支持。从本质上讲,你可以告诉
Hibernate只有一个实体的一部分应该加载到
从数据库中获取,而另一个部分也应该加载
。请注意,这与基于代理的延迟加载概念
非常不同,后者是以实体为中心的,其中实体的状态是根据需要一次加载
。使用字节码增强功能,可根据需要加载单个
属性或属性组。



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. Besides I see that in hibernate sql query 4 columns are selected.

How to fix it? I use hibernate 5.1.0 as JPA provider.

解决方案

Entity graphs are meant to control which relationships (e.g. 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. 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 (e.g. 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.

The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. 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. 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.

From the latest Hibernate docs we have:

2.3.2

fetch - FetchType (defaults to 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. Hibernate ignores this setting for basic types unless you are using bytecode enhancement.

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. 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.

这篇关于Hibernate忽略fetchgraph的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆