load()vs get()在Hibernate中的优点是什么?
任何人都可以告诉我在Hibernate中load()vs get()的优点是什么?
在Hibernate中load()vs get()的优点是什么?
资源
代理意味着,hibernate会在内存中准备一些具有给定标识符值的虚假对象,而不会触及数据库。
例如:
如果我们调用session.load(Student.class,new Integer(107));
hibernate将在id为107的内存中创build一个假Student对象[row],但是Student类的其余属性甚至不会被初始化。
资源
这些方法的语义解释并不能解释它们之间的实际区别。 实用规则如下:
-
当你想加载一个对象时使用
get()
-
当需要获取对象的引用时,使用
load()
而不发出额外的SQL查询,例如,创build与另一个对象的关系:public void savePost(long authorId, String text) { Post p = new Post(); p.setText(text); // No SELECT query here. // Existence of Author is ensured by foreign key constraint on Post. p.setAuthor(s.load(Author.class, authorId)); s.save(p); }
从“Java Persistence with Hibernate”一书,第405页:
get()和load()之间的一个区别是它们如何指示无法find实例。 如果数据库中不存在具有给定标识符值的行,则 get()返回null 。 load()方法抛出ObjectNotFoundExceptionexception 。 这是你select什么error handling你喜欢。
更重要的是, load()方法可能会返回一个代理 ,一个占位符, 而不会触及数据库 。 这样做的后果是,只要尝试访问返回的占位符并强制初始化(这也称为延迟加载;我们将在后面的章节讨论加载优化),您可能会稍后收到ObjectNotFoundExceptionexception。试图返回一个代理,并只返回一个初始化的对象实例,如果它已经由当前的持久化上下文pipe理的话。 在前面的例子中,根本没有数据库命中! 另一方面get()方法永远不会返回代理,它总是碰到数据库 。
你可能会问为什么这个选项是有用的 – 毕竟,你检索一个对象来访问它。 获取持久性实例以将其分配为另一个实例的引用是很常见的。 例如,假设您只需要将该项目用于单个用途:使用注释设置关联:aComment.setForAuction(item)。 如果这是你打算处理这个项目,代理将会很好; 没有必要击中数据库。 换句话说,当保存注释时,您需要插入到COMMENT表中的项目的外键值。 一个Item的代理只提供了:一个包装在占位符中的标识符值,看起来像真实的东西。
答:这是在hibernate参考中解释的。 一个区别是性能和另一个是负载抛出一个不可恢复的exception,当没有find对象的ID。
更多细节在这里
加载将返回一个代理对象。
get会返回一个实际的对象,如果找不到任何对象,则返回null。
- 当你想加载一个对象时使用get()
- 当需要获取对象的引用时,使用load()而不发出额外的SQL查询,例如,创build与另一个对象的关系:
例如:如果你正在尝试加载/得到empoyee对象empid = 20。 但是,假设logging在数据库中不可用。
Employee employee1 = session.load(Employee.class,20); //Step-1 system.out.println(employee1.getEmployeeId(); //Step-2 --o/p=20 system.out.println(employee1.getEmployeeName(); //Step-3 -->O/P:ObjectNotFoundException
如果你在步骤1中使用load,那么hibernate不会触发任何select查询来从DB获取雇员logging。在这个品脱hibernate给出了一个虚拟对象(Proxy)。 这个虚拟对象不包含任何东西。 这是新员工(20)。 你可以在步骤2中validation它会打印20,但是在步骤3中,我们正在尝试查找员工信息。 所以在这个时候,hibernate触发一个sql查询来获取Empoyee对象。 如果在DB.throws中找不到ObjectNotFoundException。
Employee employee2 = session.get(Employee.class,20); //Step-4
for session.get()hibernate激发一个sql查询来从db中获取数据。 所以在我们的情况下ID = 20不存在于数据库中。 所以它会返回null。
当Load被调用时,它返回一个Proxy对象。 实际的select查询仍然没有被触发。 当我们第一次使用任何映射的属性时,实际的查询被触发。 如果数据库中不存在行,则会抛出exception。 例如
Software sw = ( Software )session.load(Software.class, 12);
这里sw是代理types的。 并且select查询尚未被调用。 在Eclipsedebugging器中,您可能会看到它
sw Software$$EnhancerByCGLIB$$baf24ae0 (id=17) CGLIB$BOUND true CGLIB$CALLBACK_0 CGLIBLazyInitializer (id=23) CGLIB$CALLBACK_1 null CGLIB$CONSTRUCTED true id null prop1 null softwareprop null
当我使用
sw.getProp1()
select查询被激发。 现在,代理现在知道所有映射的属性的值。
在调用get的时候,select查询立即被触发。 返回的对象不是代理,而是实际的类。 例如
Software sw = ( Software )session.get(Software.class, 12);
这里sw是软件本身的types。 如果行存在,则所有映射的属性都用DB中的值填充。 如果行不存在,则sw将为空。
sw Software (id=17) id Integer (id=20) prop1 "prodjlt1" (id=23) softwareprop "softwrjlt1" (id=27)
所以如前所述,只有在确定DB中存在logging的情况下才使用加载。 在这种情况下,与代理一起工作是无害的,并有助于延迟DB查询,直到实际需要映射的属性为止。
性能问题也是获取和加载方法的主要区别。
get()方法在执行时立即获取数据,而load()方法返回代理对象并仅在需要对象属性时才提取数据。 所以load()方法获得更好的性能,因为它支持延迟加载。 只有当我们知道数据存在时,它才应该使用load()方法,因为当找不到数据时它会抛出exception。 如果我们要确保数据存在,我们应该使用get()方法。
简而言之,您应该了解两者之间的差异,并确定哪种方法最适合您的应用程序。
我在教程中发现了这个区别在Hibernate中get和load方法之间的区别