如何使用休眠条件懒惰地获取字段

2022-09-03 10:07:09

表的每一行(具有 和 )应读作。Personnamefirstnameage

EntityManager em = emf.createEntityManager();
Session s = (Session) em.getDelegate();
Criteria criteria = s.createCriteria(Person.class);
criteria.setFetchMode("age", FetchMode.SELECT);

但 SQL 显示

Hibernate:
    select
        person0_.name,
        person0_.firstname,
        person0_.age
    from 
        SCOPE.PERSON person0_

如何让年龄懒惰只是为了标准??


答案 1

我认为懒惰模式只有在联想时才有意义。如果您正在访问普通表,它将加载所有字段。

如果希望字段不出现在 SQL 中,因此不会加载到内存中,请使用投影:age

Criteria crit = session.createCriteria(Person.class);
ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("name"));
projList.add(Projections.property("firstname"));
crit.setProjection(projList);

答案 2

在条件上设置“age”属性的 FetchMode 不起作用,因为此时的提取策略仅适用于关联的对象,而不适用于属性。见第20.1节。获取休眠文档的策略。

如果应用程序需要导航关联,Hibernate 使用提取策略来检索关联的对象。提取策略可以在 O/R 映射元数据中声明,也可以由特定的 HQL 或条件查询覆盖。

延迟加载属性的唯一方法是将注释设置为 。请参阅此处,或者如果您使用 .hbm.xml 文件进行映射使用,请参阅休眠文档的部分。@BasicFetchType.LAZYlazy=true

@Basic注释允许您声明属性的提取策略。如果设置为 LAZY,则指定在首次访问实例变量时应延迟提取此属性。它需要生成时字节码检测,如果未检测类,则将忽略属性级延迟加载。

属性的延迟加载也使用构建时字节码插入(休眠在编译后更改实体类以允许延迟加载属性)。阅读 20.1.8。使用惰性属性提取

针对您的问题的另一个可能的解决方案(所有其他解决方案除外)是创建一个更简单的 Person 类,并使用构造函数查询,如下所示:

public class PersonDTO {
    private String name;
    private String firstname;

    private Person(String name, String firstname) {
        this.name = name;
        this.firstname = firstname;
    }
    // getters & setters
}

Query q = session.createQuery("select new your.package.name.PersonDTO("
    + "p.name, p.firstname) from Person p");
q.list();

您甚至可以使用现有的 Person 类,只需使用适当的构造函数对其进行扩展,但我更喜欢显式性。

但此处提供的所有解决方案都不会实现属性的延迟加载。执行此操作的唯一方法是注释,或者您必须实现自己的延迟加载。age@Basic


推荐