繁体   English   中英

Hibernate 中 load() 与 get() 的优势是什么?

[英]What's the advantage of load() vs get() in Hibernate?

谁能告诉我load()get()在 Hibernate 中的优势是什么?

这些方法的语义解释并没有解释它们之间的实际区别。 实际规则如下:

  • 当你想加载一个对象时使用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); }
Hibernate 中 load() 与 get() 的优势是什么?
加载() 得到()
如果您确定该对象存在,则仅使用load()方法。 如果您不确定该对象是否存在,请使用get()方法之一。
如果在数据库中找不到唯一 id, load()方法将抛出异常。 如果在数据库中找不到唯一 id, get()方法将返回 null。
load()默认只返回一个代理,并且在第一次调用代理之前不会命中数据库。 get()将立即访问数据库。

来源

代理意味着,休眠将在内存中准备一些具有给定标识符值的假对象,而不会访问数据库。
在此处输入图片说明

例如:
如果我们调用session.load(Student.class,new Integer(107));

hibernate 将在内存中创建一个 id 为 107 的伪 Student 对象 [row],但 Student 类的其余属性甚至不会被初始化。

来源

来自“Java Persistence with Hibernate”一书,第 405 页:

get() 和 load() 之间的一个区别是它们如何指示无法找到实例。 如果数据库中不存在具有给定标识符值的行,则get() 返回 null load() 方法抛出 ObjectNotFoundException 您可以选择您喜欢的错误处理方式。

更重要的是, load() 方法可以返回一个代理,一个占位符,而不会访问数据库 这样做的结果是,一旦您尝试访问返回的占位符并强制其初始化(这也称为延迟加载;我们将在后面的章节中讨论加载优化。)之后,您可能会收到 ObjectNotFoundException 异常。 load() 方法总是尝试返回一个代理,如果它已经由当前持久化上下文管理,则仅返回一个已初始化的对象实例。 在前面显示的示例中,根本没有发生数据库命中! 另一方面get() 方法从不返回代理,它总是访问数据库

您可能会问为什么这个选项有用——毕竟,您需要检索一个对象来访问它。 获取一个持久实例并将其分配为对另一个实例的引用是很常见的。 例如,假设您只需要该项目仅用于一个目的:设置与评论的关联:aComment.setForAuction(item)。 如果这就是您计划对该项目做的所有事情,那么代理就可以了; 无需访问数据库。 换句话说,当保存Comment 时,您需要插入到COMMENT 表中的项目的外键值。 Item 的代理提供的只是:一个标识符值包装在一个看起来像真实事物的占位符中。

  • 当你想加载一个对象时使用 get()
  • 当您需要在不发出额外 SQL 查询的情况下获取对对象的引用时,请使用 load(),例如,创建与另一个对象的关系:

例如:如果您尝试加载 empid=20 的 /get Empoyee 对象。 但假设记录在 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 中使用负载,休眠此时不会触发任何选择查询以从数据库中获取员工记录。此时,休眠提供了一个虚拟对象(代理)。 这个虚拟对象不包含任何东西。 它是新员工(20)。 您可以在第 2 步中验证这一点,它将打印 20。但在第 3 步中,我们正在尝试查找员工信息。 所以此时 hibernate 会触发一个 sql 查询来获取 Empoyee 对象。 如果在 DB.throws ObjectNotFoundException 中没有找到。

Employee employee2 = session.get(Employee.class,20);  //Step-4

对于 session.get() hibernate 会触发 sql 查询以从 db 获取数据。 所以在我们的例子中 id=20 不存在于数据库中。 所以它会返回null。

load 将返回一个代理对象。

get 将返回一个实际对象,如果找不到任何对象,则返回 null。

性能问题也是 get 和 load 方法之间的主要区别。

get() 方法在执行后立即获取数据,而 load() 方法返回代理对象,并且仅在需要对象属性时获取数据。 使 load() 方法获得更好的性能,因为它支持延迟加载。 只有当我们知道数据存在时才应该使用 load() 方法,因为它在找不到数据时抛出异常。 如果我们想确保数据存在,我们应该使用 get() 方法。

简而言之,您应该了解两者之间的差异,并决定哪种方法最适合您的应用程序。

我在教程中发现了这个差异Hibernate 中 get 和 load 方法之间差异

答:这在 hibernate 参考资料中有解释。 一个区别是性能,另一个区别是当没有找到 ID 的对象时,加载会抛出一个不可恢复的异常。

更多细节在这里

当 Load 被调用时,它返回一个 Proxy 对象。 仍然没有触发实际的选择查询。 当我们第一次使用任何映射属性时,将触发实际查询。 如果数据库中不存在行,它将抛出异常。 例如

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()

选择查询被触发。 现在代理现在知道所有映射属性的值。

当调用 get 时,会立即触发选择查询。 返回的对象不是代理而是实际类。 例如

Software sw = ( Software )session.get(Software.class, 12);

这里 sw 是软件本身的类型。 如果行存在,则所有映射的属性都使用 DB 中的值填充。 如果行不存在,则 sw 将为空。

sw  Software  (id=17)   
id  Integer  (id=20)    
prop1   "prodjlt1" (id=23)  
softwareprop    "softwrjlt1" (id=27)    

因此,一如既往,仅当您确定 DB 中确实存在该记录时才使用 load。 在这种情况下,使用代理是无害的,并且将有助于延迟数据库查询,直到实际需要映射的属性。

session.load() :它将始终返回具有给定标识值的代理对象,即使该标识值在数据库中不存在。 但是,当您尝试通过从数据库中检索代理的属性来初始化代理时,它将使用 select 语句访问数据库。 如果未找到任何行,则会抛出 ObjectNotFoundException。

session.get() :如果在数据库中找不到标识值,它将始终返回 null 。

Get() 通过从数据库或休眠缓存中获取对象来返回对象,而 load() 仅返回可能实际上不存在的对象的引用,它仅在您访问对象的其他属性时才从数据库或缓存加载数据。

使用 load(),我们可以打印 id,但是一旦我们尝试访问其他字段,它就会触发数据库查询并在没有找到具有给定标识符的记录时抛出 org.hibernate.ObjectNotFoundException。 它是休眠特定的运行时异常,因此我们不需要明确捕获它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM