Hibernate:session.get 和 session.load 之间的区别
从API中我可以看出它与代理有关。 但我找不到很多关于代理的信息,也不明白调用 session.get
和 session.load
之间的区别。 有人可以解释一下或引导我到参考页面吗?
谢谢你!!
From the API, I could see it has something to do with proxy. But I couldn't find a lot of information on proxy and do not understand the difference between calling session.get
and session.load
. Could someone please explain or direct me to a reference page?
Thank you!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
来自 Hibernate 论坛:
通过标识符检索对象
以下 Hibernate 代码片段从数据库中检索 User 对象:
get() 方法很特殊,因为标识符唯一标识单个用户
一个类的实例。 因此,应用程序通常使用标识符作为
持久对象的方便句柄。 通过标识符检索可以使用缓存
检索对象时,如果该对象已缓存,则避免数据库命中。
Hibernate还提供了load()方法:
load()方法比较旧; get() 被添加到 Hibernate 的 API 由于用户
要求。 区别是微不足道的:
如果 load() 在缓存或数据库中找不到对象,则会出现异常
抛出。 load() 方法永远不会返回 null。 get() 方法返回
如果找不到该对象,则返回 null。
load() 方法可能返回代理而不是真正的持久实例。
代理是一个占位符,当真实对象被加载时,它会触发加载。
第一次访问; 上
另一方面, get() 永远不会返回代理。
在 get() 和 load() 之间进行选择很容易:如果您确定持久性
对象存在,不存在将被视为例外,load() 是一个
不错的选择。 如果您不确定是否存在具有给定的持久实例
标识符,使用 get() 并测试返回值是否为 null。 使用 load() 有
进一步的含义:应用程序可以检索对某个对象的有效引用(代理)
持久实例,无需访问数据库来检索其持久状态。 所以
load() 在找不到持久对象时可能不会抛出异常
在缓存或数据库中; 稍后当代理时会抛出异常
被访问。
当然,通过标识符检索对象并不像使用任意标识符那样灵活
查询。
From the Hibernate forum:
Retrieving objects by identifier
The following Hibernate code snippet retrieves a User object from the database:
The get() method is special because the identifier uniquely identifies a single
instance of a class. Hence it’s common for applications to use the identifier as a
convenient handle to a persistent object. Retrieval by identifier can use the cache
when retrieving an object, avoiding a database hit if the object is already cached.
Hibernate also provides a load() method:
The load() method is older; get() was added to Hibernate’s API due to user
request. The difference is trivial:
If load() can’t find the object in the cache or database, an exception is
thrown. The load() method never returns null. The get() method returns
null if the object can’t be found.
The load() method may return a proxy instead of a real persistent instance.
A proxy is a placeholder that triggers the loading of the real object when it’s
accessed for the first time; On the
other hand, get() never returns a proxy.
Choosing between get() and load() is easy: If you’re certain the persistent
object exists, and nonexistence would be considered exceptional, load() is a
good option. If you aren’t certain there is a persistent instance with the given
identifier, use get() and test the return value to see if it’s null. Using load() has
a further implication: The application may retrieve a valid reference (a proxy) to a
persistent instance without hitting the database to retrieve its persistent state. So
load() might not throw an exception when it doesn’t find the persistent object
in the cache or database; the exception would be thrown later, when the proxy
is accessed.
Of course, retrieving an object by identifier isn’t as flexible as using arbitrary
queries.
好吧,至少在nhibernate中,session.Get(id)将从数据库加载对象,而session.Load(id)只创建一个代理对象,而不会离开服务器。 与 POCO(或 POJO:)中的所有其他延迟加载属性一样工作。 然后,您可以使用此代理作为对对象本身的引用来创建关系等。可以将
其想象为一个仅保留 Id 的对象,并且在您需要时将加载其余内容。 如果您只是传递它来创建关系(例如 FK),那么 id 就是您所需要的。
Well, in nhibernate at least, session.Get(id) will load the object from the database, while session.Load(id) only creates a proxy object to it without leaving your server. Works just like every other lazy-loaded property in your POCOs (or POJOs :). You can then use this proxy as a reference to the object itself to create relationships, etc.
Think of it like having an object that only keeps the Id and that will load the rest if you ever need it. If you're just passing it around to create relationships (like FKs), the id is all you'll ever need.
session.load() 将始终返回一个“代理”(Hibernate 术语),而不访问数据库。 在Hibernate中,代理是一个具有给定标识符值的对象,它的属性尚未初始化,它只是看起来像一个临时的假对象。
如果没有找到行,它将抛出 ObjectNotFoundException。
session.get() 始终访问数据库并返回真实对象,即代表数据库行的对象,而不是代理。
如果没有找到行,则返回 null。
这些方法的性能也使 diff 变得不同。 两个人之间...
session.load() will always return a “proxy” (Hibernate term) without hitting the database. In Hibernate, proxy is an object with the given identifier value, its properties are not initialized yet, it just look like a temporary fake object.
If no row found , it will throws an ObjectNotFoundException.
session.get() always hit the database and return the real object, an object that represent the database row, not proxy.
If no row found , it return null.
Performance with these methods also makes diff . between two...
还有一点额外的一点:
如果在缓存和数据库中都没有找到对象,Hibernate Session 类的 get 方法将返回 null。
如果在缓存和数据库中都找不到对象,则 load() 方法会抛出 ObjectNotFoundException,但不会返回 null。
One more Extra point::
get method of Hibernate Session class returns null if object is not found in cache as well as on database.
while load() method throws ObjectNotFoundException if object is not found on cache as well as on database but never return null.
使用“load”而不是“get”的一个间接后果是使用版本属性的乐观锁定可能无法按您的预期工作。 如果加载只是创建代理而不从数据库读取,则不会加载版本属性。 仅当您稍后引用对象上的属性并触发选择时,才会加载该版本。 与此同时,另一个会话可以更新该对象,并且您的会话将没有执行乐观锁检查所需的原始版本 - 因此您的会话的更新将覆盖另一个会话的更新,而不会发出任何警告。
下面尝试用两个会话处理具有相同标识符的对象来勾勒出这个场景。 DB 中对象的初始版本是 10。
我们实际上希望会话 1 的提交因乐观锁异常而失败,但这里会成功。
使用“get”而不是“load”可以解决该问题,因为 get 将立即发出选择,并且版本号将在正确的时间加载以进行乐观锁检查。
One indirect consequence of using "load" instead of "get" is that optimistic locking using a version attribute may not work as you'd expect. If a load simply creates a proxy and does not read from the database, the version property is not loaded. The version will only be loaded when/if you later refer to a property on the object, triggering a select. In the meantime, another session can update the object, and your session will not have the original version that it needs to do the optimistic lock check - so your session's update will overwrite the other session's update with no warning.
Here's an attempt to sketch out this scenario with two sessions working with an object with the same identifier. Initial version for object in DB is 10.
We actually want session 1's commit to fail with an optimistic lock exception, but it will succeed here.
Using "get" instead of "load" works around the problem, because get will immediately issue a select, and the version numbers will be loaded at the correct times for the optimistic lock checking.
另外,我们在使用 load 时必须小心,因为如果对象不存在,它会抛出异常。 仅当我们确定该对象存在时才必须使用它。
Also we have to be careful while using load as it will throw an exception if the object is not present. We have to use it only when we are sure that object exists.
一个很好的解释可以在 http://www.mkyong 找到.com/hibernate/difference- Between-session-get-and-session-load
session.load() :
它总是会返回一个“代理”(Hibernate术语),而不访问数据库。
在Hibernate中,代理是一个具有给定标识符值的对象,它的属性尚未初始化,它只是看起来像一个临时的假对象。< br>
它将始终返回具有给定标识值的代理对象,即使数据库中不存在该标识值。 但是,当您尝试通过从数据库检索代理的属性来初始化代理时,它将使用 select 语句访问数据库。 如果没有找到行,则会抛出 ObjectNotFoundException。
session.get() :
它总是访问数据库(如果在缓存中找不到)并返回真实对象,即代表数据库行的对象,而不是代理。
如果没有找到行,则返回 null。
An excellent explanation is found at http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load() :
It will always return a “proxy” (Hibernate term) without hitting the database.
In Hibernate, proxy is an object with the given identifier value, its properties are not initialized yet, it just look like a temporary fake object.
It will always return a proxy object with the given identity value, even the identity value is not exists in database. However, when you try to initialize a proxy by retrieve it’s properties from database, it will hit the database with select statement. If no row is found, a ObjectNotFoundException will throw.
session.get() :
It always hit the database(if not found in cache) and return the real object, an object that represent the database row, not proxy.
If no row found , it return null.
load() 无法从缓存或数据库中找到对象,会抛出异常,并且 load() 方法永远不会返回 null。
如果找不到对象,get() 方法将返回 null。 load() 方法可能返回代理而不是真正的持久实例 get() 永远不会返回代理。
load() can’t find the object from cache or database, an exception is thrown and the load() method never returns null.
get() method returns null if the object can’t be found. The load() method may return a proxy instead of a real persistent instance get() never returns a proxy.