FetchType的区别是什么。LAZY和FetchType。Java持久性API中的EAGER ?


当前回答

如果你在使用Hibernate,你可以在调用getStudents()方法时调用Hibernate.initialize():

Public class UniversityDaoImpl extends GenericDaoHibernate<University, Integer> implements UniversityDao {
    //...
    @Override
    public University get(final Integer id) {
        Query query = getQuery("from University u where idUniversity=:id").setParameter("id", id).setMaxResults(1).setFetchSize(1);
        University university = (University) query.uniqueResult();
        ***Hibernate.initialize(university.getStudents());***
        return university;
    }
    //...
}

其他回答

基本上,

LAZY = fetch when needed
EAGER = fetch immediately

有一个小小的评论: 如果你使用惰性类型,如果你关闭会话,你以后将不能从数据库中获取数据(参见下面的输出)。

但是对于Eager类型,你在获取Instructor的同时获取数据,所以在session.close()之后,你将能够使用/显示这些课程列表数据。

  @OneToMany(//fetch = FetchType.EAGER, 
        fetch = FetchType.LAZY,  
           mappedBy = "instructor",        
           cascade = {CascadeType.DETACH, CascadeType.MERGE,
                CascadeType.PERSIST, CascadeType.REFRESH})
private List<Course> courseList; 

我建议在调试模式下尝试这两种方法。在这种情况下,我使用惰性类型,你可以看到。

 try {
        //start the transaction
        session.beginTransaction();

        //Get instructor from database
        int instructorId = 7;

        Instructor tempInstructor = session.get(Instructor.class,instructorId);

        System.out.println("Instructor: "+tempInstructor);


        //commit transaction
        session.getTransaction().commit();

       //close session
       session.close();

       //since courselist is lazy loaded... this should fail
       //so in here we are not able to fetch courselist data
       //get courses
        System.out.println("Courses "+tempInstructor.getCourseList() );


        System.out.println("Done!");

    } finally {
        session.close();
        factory.close();
    }
}

输出异常:

Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.exercise.hibernate.entity.Instructor.courseList, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:606)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:218)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:585)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:149)
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:621)
at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:453)
at java.base/java.lang.StringConcatHelper.simpleConcat(StringConcatHelper.java:408)
at com.exercise.hibernate.main.EagerLazyLoading.main(EagerLazyLoading.java:56)

如果你在使用Hibernate,你可以在调用getStudents()方法时调用Hibernate.initialize():

Public class UniversityDaoImpl extends GenericDaoHibernate<University, Integer> implements UniversityDao {
    //...
    @Override
    public University get(final Integer id) {
        Query query = getQuery("from University u where idUniversity=:id").setParameter("id", id).setMaxResults(1).setFetchSize(1);
        University university = (University) query.uniqueResult();
        ***Hibernate.initialize(university.getStudents());***
        return university;
    }
    //...
}

LAZY:它惰性地获取子实体,即在获取父实体时,它只是获取子实体的代理(由cglib或任何其他实用程序创建),当你访问子实体的任何属性时,它实际上是由hibernate获取的。

EAGER:它与父实体一起获取子实体。

为了更好地理解,请参阅Jboss文档,或者使用hibernate。Show_sql =true,检查hibernate发出的查询。

FetchType。LAZY和FetchType。EAGER用于定义默认的读取计划。

不幸的是,您只能覆盖LAZY抓取的默认抓取计划。EAGER抓取不太灵活,可能导致许多性能问题。

我的建议是克制将关联设置为EAGER的冲动,因为取回是查询时的责任。因此,您的所有查询都应该使用fetch指令来只检索当前业务用例所需的内容。