简体   繁体   English

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

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

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

Explanation of semantics of these methods doesn't explain the practical difference between them.这些方法的语义解释并没有解释它们之间的实际区别。 Practical rule is the following:实际规则如下:

  • Use get() when you want to load an object当你想加载一个对象时使用get()

  • Use load() when you need to obtain a reference to the object without issuing extra SQL queries, for example, to create a relationship with another object:当您需要在不发出额外 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); }
Whats the advantage of load() vs get() in Hibernate? Hibernate 中 load() 与 get() 的优势是什么?
load()加载() get()得到()
Only use load() method if you are sure that the object exists.如果您确定该对象存在,则仅使用load()方法。 If you are not sure that the object exist, then use one of get() methods.如果您不确定该对象是否存在,请使用get()方法之一。
load() method will throw an exception if the unique id is not found in the database.如果在数据库中找不到唯一 id, load()方法将抛出异常。 get() method will return null if the unique id is not found in the database.如果在数据库中找不到唯一 id, get()方法将返回 null。
load() just returns a proxy by default and database won't be hit until the proxy is first invoked. load()默认只返回一个代理,并且在第一次调用代理之前不会命中数据库。 get() will hit the database immediately. get()将立即访问数据库。

source 来源

Proxy means, hibernate will prepare some fake object with given identifier value in the memory without hitting a database.代理意味着,休眠将在内存中准备一些具有给定标识符值的假对象,而不会访问数据库。
在此处输入图片说明

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

hibernate will create one fake Student object [row] in the memory with id 107, but remaining properties of Student class will not even be initialized. hibernate 将在内存中创建一个 id 为 107 的伪 Student 对象 [row],但 Student 类的其余属性甚至不会被初始化。

Source 来源

From the "Java Persistence with Hibernate" book, page 405:来自“Java Persistence with Hibernate”一书,第 405 页:

The one difference between get() and load() is how they indicate that the instance could not be found. get() 和 load() 之间的一个区别是它们如何指示无法找到实例。 If no row with the given identifier value exists in the database, get() returns null .如果数据库中不存在具有给定标识符值的行,则get() 返回 null The load() method throws an ObjectNotFoundException . load() 方法抛出 ObjectNotFoundException It's your choice what error-handling you prefer.您可以选择您喜欢的错误处理方式。

More important, t he load() method may return a proxy , a placeholder, without hitting the database .更重要的是, load() 方法可以返回一个代理,一个占位符,而不会访问数据库 A consequence of this is that you may get an ObjectNotFoundException later, as soon as you try to access the returned placeholder and force its initialization (this is also called lazy loading; we discuss load optimization in later chapters.) The load() method always tries to return a proxy, and only returns an initialized object instance if it's already managed by the current persistence context.这样做的结果是,一旦您尝试访问返回的占位符并强制其初始化(这也称为延迟加载;我们将在后面的章节中讨论加载优化。)之后,您可能会收到 ObjectNotFoundException 异常。 load() 方法总是尝试返回一个代理,如果它已经由当前持久化上下文管理,则仅返回一个已初始化的对象实例。 In the example shown earlier, no database hit occurs at all!在前面显示的示例中,根本没有发生数据库命中! The get() method on the other hand never returns a proxy, it always hits the database .另一方面get() 方法从不返回代理,它总是访问数据库

You may ask why this option is useful—after all, you retrieve an object to access it.您可能会问为什么这个选项有用——毕竟,您需要检索一个对象来访问它。 It's common to obtain a persistent instance to assign it as a reference to another instance.获取一个持久实例并将其分配为对另一个实例的引用是很常见的。 For example, imagine that you need the item only for a single purpose: to set an association with a Comment: aComment.setForAuction(item).例如,假设您只需要该项目仅用于一个目的:设置与评论的关联:aComment.setForAuction(item)。 If this is all you plan to do with the item, a proxy will do fine;如果这就是您计划对该项目做的所有事情,那么代理就可以了; there is no need to hit the database.无需访问数据库。 In other words, when the Comment is saved, you need the foreign key value of an item inserted into the COMMENT table.换句话说,当保存Comment 时,您需要插入到COMMENT 表中的项目的外键值。 The proxy of an Item provides just that: an identifier value wrapped in a placeholder that looks like the real thing. Item 的代理提供的只是:一个标识符值包装在一个看起来像真实事物的占位符中。

  • Use get() when you want to load an object当你想加载一个对象时使用 get()
  • Use load() when you need to obtain a reference to the object without issuing extra SQL queries, for example, to create a relationship with another object:当您需要在不发出额外 SQL 查询的情况下获取对对象的引用时,请使用 load(),例如,创建与另一个对象的关系:

Ex: if you are trying to load /get Empoyee object where empid=20.例如:如果您尝试加载 empid=20 的 /get Empoyee 对象。 But assume record is not available in DB.但假设记录在 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

If you use load in step-1 hibernate wont fire any select query to fetch employee record from DB at this moment.At this pint hibernate gives a dummy object ( Proxy ).如果您在步骤 1 中使用负载,休眠此时不会触发任何选择查询以从数据库中获取员工记录。此时,休眠提供了一个虚拟对象(代理)。 This dummy object doesnt contain anything.这个虚拟对象不包含任何东西。 it is new Employee(20).它是新员工(20)。 you can verify this in step-2 it will print 20. but in step-3 we are trying to find employee information.您可以在第 2 步中验证这一点,它将打印 20。但在第 3 步中,我们正在尝试查找员工信息。 so at this time hibernate fires a sql query to fetch Empoyee objct.所以此时 hibernate 会触发一个 sql 查询来获取 Empoyee 对象。 If it is not found in DB.throws ObjectNotFoundException.如果在 DB.throws ObjectNotFoundException 中没有找到。

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

for session.get() hibernate fires a sql query to fetch the data from db.对于 session.get() hibernate 会触发 sql 查询以从 db 获取数据。 so in our case id=20 not exists in DB.所以在我们的例子中 id=20 不存在于数据库中。 so it will return null.所以它会返回null。

load will return a proxy object. load 将返回一个代理对象。

get will return a actual object, and returns null if it wont find any object. get 将返回一个实际对象,如果找不到任何对象,则返回 null。

The performance issues is also major difference between get and load method.性能问题也是 get 和 load 方法之间的主要区别。

The get() method fetches data as soon as it's executed while the load() method returns a proxy object and fetches only data when object properties is required. get() 方法在执行后立即获取数据,而 load() 方法返回代理对象,并且仅在需要对象属性时获取数据。 So that the load() method gets better performance because it support lazy loading.使 load() 方法获得更好的性能,因为它支持延迟加载。 Whe should use the load() method only when we know data exists because it throws exception when data is not found.只有当我们知道数据存在时才应该使用 load() 方法,因为它在找不到数据时抛出异常。 In case we want to make sure data exists we should use the get() method.如果我们想确保数据存在,我们应该使用 get() 方法。

In short, you should understand the differential in between, and decide which method is best fix in your application.简而言之,您应该了解两者之间的差异,并决定哪种方法最适合您的应用程序。

I found this differences on the tutorial Difference between get and load method in Hibernate我在教程中发现了这个差异Hibernate 中 get 和 load 方法之间差异

A: This is explained in the hibernate reference.答:这在 hibernate 参考资料中有解释。 One difference was performance and the other one is that load throws an unrecoverable Exception when no Object is found for the ID.一个区别是性能,另一个区别是当没有找到 ID 的对象时,加载会抛出一个不可恢复的异常。

More details here更多细节在这里

When Load is called it returns a Proxy object.当 Load 被调用时,它返回一个 Proxy 对象。 Actual select query is still not fired.仍然没有触发实际的选择查询。 When we use any of the mapped property for the first time the actual query is fired.当我们第一次使用任何映射属性时,将触发实际查询。 If row does not exist in DB it will throw exception.如果数据库中不存在行,它将抛出异常。 eg例如

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

Here sw is of proxy type.这里 sw 是代理类型。 And select query is not yet called.并且尚未调用选择查询。 in Eclipse debugger you may see it like在 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 

when I use当我使用

 sw.getProp1()

the select query is fired.选择查询被触发。 And now proxy now knows values for all the mapped properties.现在代理现在知道所有映射属性的值。

Where as when get is called, select query is fired immediately.当调用 get 时,会立即触发选择查询。 The returned object is not proxy but of actual class.返回的对象不是代理而是实际类。 eg例如

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

Here sw is of type Software itself.这里 sw 是软件本身的类型。 If row exists then all mapped properties are populated with the values in DB.如果行存在,则所有映射的属性都使用 DB 中的值填充。 If row does not exist then sw will be null.如果行不存在,则 sw 将为空。

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

So as always said, use load only if you are sure that record does exist in DB.因此,一如既往,仅当您确定 DB 中确实存在该记录时才使用 load。 In that case it is harmless to work with the proxy and will be helpful delaying DB query till the mapped property is actually needed.在这种情况下,使用代理是无害的,并且将有助于延迟数据库查询,直到实际需要映射的属性。

session.load() : It will always return a proxy object with the given identity value, even the identity value is not exists in database. session.load() :它将始终返回具有给定标识值的代理对象,即使该标识值在数据库中不存在。 However, when you try to initialize a proxy by retrieve it's properties from database, it will hit the database with select statement.但是,当您尝试通过从数据库中检索代理的属性来初始化代理时,它将使用 select 语句访问数据库。 If no row is found, a ObjectNotFoundException will throw.如果未找到任何行,则会抛出 ObjectNotFoundException。

session.get() : It will always return null , if the identity value is not found in database. session.get() :如果在数据库中找不到标识值,它将始终返回 null 。

Get() returns the object by fetching it from database or from hibernate cache whereas load() just returns the reference of an object that might not actually exists, it loads the data from database or cache only when you access other properties of the object. Get() 通过从数据库或休眠缓存中获取对象来返回对象,而 load() 仅返回可能实际上不存在的对象的引用,它仅在您访问对象的其他属性时才从数据库或缓存加载数据。

With load(), we are able to print the id but as soon as we try to access other fields, it fires database query and throws org.hibernate.ObjectNotFoundException if there is no record found with the given identifier.使用 load(),我们可以打印 id,但是一旦我们尝试访问其他字段,它就会触发数据库查询并在没有找到具有给定标识符的记录时抛出 org.hibernate.ObjectNotFoundException。 It's hibernate specific Runtime Exception, so we don't need to catch it explicitly.它是休眠特定的运行时异常,因此我们不需要明确捕获它。

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

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