Hibernate忽略了fetchgraph

这是我的实体:

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 } 

这就是我获取人员名单的方式:

 Query query = em.createQuery("Select p from PersonItem p WHERE p.guid IN (:guids)"); EntityGraph 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 list=query.getResultList(); em.close(); // And now I iterate result AFTER EM CLOSE ....iterate 

如果我理解了fetch图,它必须只加载我指定的那些字段。 但是,字段“birthDate”也被加载。 此外我看到在hibernate sql查询中选择了4列。

怎么解决? 我使用hibernate 5.1.0作为JPA提供程序。

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

Hibernate对此有一些支持,但是这里描述起来相当困难。 然而,他们提到了对这种方法的以下缄默(我完全同意):

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

所以我不建议你走这条路太远,直到你确认这确实是你的应用程序的瓶颈(例如,这种提取调整可能是过早优化的症状)。

更新:

正如所指出的那样,JPA确实会向提供者提供关于是否延迟提取简单列(非关联)的信息。

EAGER策略是持久性提供程序运行时的要求,必须急切地获取数据。 LAZY策略是对持久性提供程序运行时的一个提示,即数据在首次访问时应该被懒惰地获取。 允许实现急切地获取已指定LAZY策略提示的数据。 特别是,延迟提取可能仅适用于使用基于属性的访问的基本映射。

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

从最新的Hibernate文档中我们得到:

2.3.2

fetch – FetchType(默认为EAGER)

定义是否应该急切地或懒惰地获取此属性。 JPA表示EAGER是提供者(Hibernate)要求在获取所有者时获取值的要求,而LAZY仅仅是在访问属性时提取值的提示。 除非使用字节码增强,否则Hibernate会忽略基本类型的此设置。

这个下一个片段描述了字节码增强的优点。

延迟属性加载

将此视为部分加载支持。 从本质上讲,你可以告诉Hibernate,只有在从数据库中取出时才加载实体的一部分,以及何时加载其他部分。 请注意,这与基于代理的延迟加载概念非常不同,后者是以实体为中心的,其中根据需要立即加载实体的状态。 通过字节码增强,可以根据需要加载单个属性或属性组。