FetchType的区别是什么。LAZY和FetchType。Java持久性API中的EAGER ?
当前回答
JOIN很重要
轻松地看待它:
假设我们有一个叫User的类和另一个叫Address的类,假设每个用户都有一个或多个地址,意思是关系(一对多),如果执行:
FetchType。LAZY执行sql命令,就像没有join一样:
SELECT * FROM users
FetchType。执行sql命令:
SELECT * FROM users u join address a on a.user_id = u.user_id
注意:以上查询只是为您澄清图像,但Hibernate框架实际执行的查询与上述查询类似。
哪种获取类型更好?
由于Eager抓取会自动加载所有关系,这是一个很大的性能消耗 除非被告知,否则惰性抓取不会加载任何关系,这将带来更好的性能 即时抓取使得编程更容易,因为需要的代码更少 如果整个系统没有经过适当的测试,延迟加载可能会导致错误(异常) 考虑到所有因素,您仍然应该更喜欢Lazy加载而不是Eager加载,因为它的性能更好
如果你正在使用Spring引导框架,那么就进入应用程序。属性文件并添加下面的命令以了解到底发生了什么。
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
其他回答
这两种类型的抓取之间的主要区别是数据加载到内存中的时刻。 我附上了2张照片来帮助你理解这一点。
急于获取
延迟获取
public enum FetchType extends java.lang.Enum Defines strategies for fetching data from the database. The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified. Example: @Basic(fetch=LAZY) protected String getName() { return name; }
源
基本上,
LAZY = fetch when needed
EAGER = fetch immediately
如果你在使用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;
}
//...
}
有一个小小的评论: 如果你使用惰性类型,如果你关闭会话,你以后将不能从数据库中获取数据(参见下面的输出)。
但是对于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)
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 原则-如何打印出真正的sql,而不仅仅是准备好的语句?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder