9

这是我的实体:

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

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

如何解决?我使用休眠 5.1.0 作为 JPA 提供程序。

4

1 回答 1

7

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

Hibernate 对此有一些支持,但要开始工作相当困难,在此处进行了描述。然而,他们提到了以下对这种方法的沉默(我完全同意):

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

因此,在您确认这确实是您的应用程序中的瓶颈之前,我不建议您在这条路上走得太远(例如,这种获取调整可能是过早优化的症状)。

更新:

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

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

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

根据我们最新的 Hibernate 文档

2.3.2

fetch - FetchType(默认为 EAGER)

定义是否应该急切地或延迟地获取此属性。JPA 说 EAGER 是对提供者(Hibernate)的要求,即在获取所有者时应该获取值,而 LAZY 只是提示在访问属性时获取值。Hibernate 忽略基本类型的这个设置,除非你使用字节码增强。

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

延迟属性加载

将此视为部分加载支持。从本质上讲,您可以告诉 Hibernate,在从数据库中获取实体时,应该只加载实体的一部分,并且什么时候也应该加载其他部分。请注意,这与基于代理的延迟加载思想有很大不同,延迟加载是以实体为中心,根据需要立即加载实体的状态。通过字节码增强,可以根据需要加载单个属性或属性组。

于 2016-05-05T18:52:08.413 回答