任何人都可以告诉我在Hibernate中load()vs get()的优势是什么?
答案 0 :(得分:63)
这些方法的语义解释并不能解释它们之间的实际区别。实际规则如下:
如果要加载对象,请使用get()
当您需要获取对象的引用而不发出额外的SQL查询(例如,与另一个对象创建关系)时,请使用load()
:
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);
}
答案 1 :(得分:38)
在Hibernate中,load()vs get()的优势是什么?
代理意味着,hibernate将在内存中准备一些具有给定标识符值的虚假对象而不会访问数据库。
例如:
如果我们致电session.load(Student.class,new Integer(107));
hibernate会在id为107的内存中创建一个伪Student对象[row],但是Student类的剩余属性甚至都不会被初始化。
答案 2 :(得分:31)
来自“Java Persistence with Hibernate”一书,第405页:
get()和load()之间的一个区别是它们如何表示 无法找到实例。 如果没有具有给定标识符的行 值存在于数据库中, get()返回null 。 load()方法 抛出ObjectNotFoundException 。这是你的选择 你喜欢的错误处理。
更重要的是,t 他的load()方法可能 返回代理,占位符,无需访问数据库。一个 这样做的结果是你可能会得到一个ObjectNotFoundException 稍后,只要您尝试访问返回的占位符并强制使用 它的初始化(这也称为延迟加载;我们讨论加载 在后面的章节中进行优化。)load()方法总是尝试 返回一个代理,只返回一个初始化的对象实例if 它已经由当前的持久化上下文管理。在里面 前面显示的示例,根本没有发生数据库命中! get()方法 另一方面,永远不会返回代理,它总是命中数据库。
您可能会问为什么这个选项很有用 - 毕竟,您检索了一个 要访问它的对象。获取持久化实例是很常见的 将其指定为另一个实例的引用。例如,想象一下 您只需要将该项目用于一个目的:设置一个 与评论相关联:aComment.setForAuction(item)。如果是这样的话 所有你打算用这个项目,一个代理会做得很好;没有 需要打到数据库。换句话说,当评论被保存时, 您需要插入到COMMENT中的项的外键值 表。 Item的代理提供了:标识符值 包裹在看似真实的占位符中。
答案 3 :(得分:5)
load将返回一个代理对象。
get将返回一个实际对象,如果它找不到任何对象,则返回null。
答案 4 :(得分:4)
答:这在hibernate参考中有解释。一个区别是性能,另一个是当没有为ID找到Object时,load会抛出一个不可恢复的异常。
更多详情here
答案 5 :(得分:3)
例如:如果您尝试加载/获取Empoyee对象,其中empid = 20。但假设记录在DB中不可用。
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不会触发任何选择查询,以便此时从DB获取员工记录。这个品脱的hibernate给出了一个虚拟对象(Proxy)。这个虚拟对象不包含任何内容。这是新员工(20)。您可以在步骤2中验证这一点 它将打印20.但在第3步,我们正在尝试查找员工信息。所以此时hibernate会触发一个sql查询来获取Empoyee对象。如果在DB.throws ObjectNotFoundException中找不到它。
Employee employee2 = session.get(Employee.class,20); //Step-4
对于session.get(),hibernate会触发一个sql查询来从db中获取数据。所以在我们的例子中,DB = 20中不存在id = 20。所以它将返回null。
答案 6 :(得分:2)
调用Load时,它返回一个Proxy对象。仍未触发实际选择查询。当我们第一次使用任何映射属性时,会触发实际查询。如果DB中不存在行,则会抛出异常。 e.g。
Software sw = ( Software )session.load(Software.class, 12);
这里sw是代理类型。并且尚未调用选择查询。 在Eclipse调试器中,您可能会看到它像
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查询。返回的对象不是代理,而是实际的类。 e.g。
Software sw = ( Software )session.get(Software.class, 12);
这里sw属于Software本身。如果存在行,则使用DB中的值填充所有映射的属性。如果row不存在则sw将为null。
sw Software (id=17)
id Integer (id=20)
prop1 "prodjlt1" (id=23)
softwareprop "softwrjlt1" (id=27)
如前所述,只有在确定DB中存在记录时才使用load。在这种情况下,使用代理是无害的,并且有助于延迟数据库查询,直到实际需要映射的属性。
答案 7 :(得分:2)
性能问题也是get和load方法之间的主要区别。
get()方法在执行时会立即获取数据,而load()方法返回代理对象,并在需要对象属性时仅提取数据。 这样load()方法可以获得更好的性能,因为它支持延迟加载。 只有当我们知道数据存在时才应该使用load()方法,因为它在未找到数据时抛出异常。 如果我们想确保数据存在,我们应该使用get()方法。
简而言之,您应该了解它们之间的差异,并确定哪种方法最适合您的应用程序。
中发现了这些差异答案 8 :(得分:1)
<强> session.load()强>: 它将始终返回具有给定标识值的代理对象,即使数据库中不存在标识值。但是,当您尝试通过从数据库检索它的属性来初始化代理时,它将使用select语句命中数据库。如果没有找到行,则抛出ObjectNotFoundException。
<强> session.get()强>: 如果在数据库中找不到标识值,它将始终返回null。
答案 9 :(得分:0)
Get()通过从数据库或休眠缓存中获取对象来返回对象,而load()仅返回可能不存在的对象的引用,仅当您访问数据库的其他属性时,它才从数据库或缓存中加载数据对象。
使用load(),我们可以打印id,但是一旦尝试访问其他字段,它就会触发数据库查询,如果没有找到具有给定标识符的记录,则会引发org.hibernate.ObjectNotFoundException。它是休眠专用的运行时异常,因此我们无需显式捕获它。