如何使用Hibernate Criteria懒洋洋地获取字段

Pet*_*der 15 java orm hibernate lazy-loading fetch

该表的每一行Person(有name,firstnameage)应阅读.

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

但SQL显示

Hibernate:
    select
        person0_.name,
        person0_.firstname,
        person0_.age
    from 
        SCOPE.PERSON person0_
Run Code Online (Sandbox Code Playgroud)

如何让年龄懒惰适用于标准?

Pac*_*ato 11

我认为懒惰模式只对协会有意义.如果您正在访问普通表,它将加载所有字段.

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

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


Mat*_*ert 9

在条件上设置"age"属性的FetchMode没有任何效果,因为此时的提取策略仅适用于关联对象,但不适用于属性.见第20.1.获取 hibernate文档的策略.

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

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

@Basic注释允许您声明属性提取策略.如果设置为LAZY,则指定在首次访问实例变量时应该懒惰地获取此属性.它需要构建时字节码检测,如果没有检测类,则会默默忽略属性级延迟加载.

延迟加载属性也使用构建时字节码实例(hibernate在编译后更改实体类以允许延迟加载属性).阅读20.1.8.使用lazy属性获取

您的问题的另一个可能的解决方案(除了所有其他解决方案)是创建一个更简单的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();
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用现有的Person类,只需使用适当的构造函数扩展它,但我更喜欢显式.

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