从API中,我可以看到它与代理有关。但是我找不到很多关于代理的信息,也不明白拨打session.get
和session.load
之间的区别。有人可以解释或指引我参考页面吗?休眠:session.get和session.load之间的区别
谢谢!
从API中,我可以看到它与代理有关。但是我找不到很多关于代理的信息,也不明白拨打session.get
和session.load
之间的区别。有人可以解释或指引我参考页面吗?休眠:session.get和session.load之间的区别
谢谢!
这从本书在Hibernate的行动。好一个阅读本..
由标识符 检索对象下面的休眠代码片段从数据库检索用户对象:
User user = (User) session.get(User.class, userID);
的get()方法是特殊的,因为该标识符唯一标识一个类的单个实例。因此,应用程序通常使用该标识符作为持久对象的方便句柄。通过标识符检索可以在检索对象时使用高速缓存 ,如果对象已被高速缓存,则避免数据库命中。 Hibernate也提供了一个负载()方法:
User user = (User) session.load(User.class, userID);
负载()方法是老年人;由于用户 请求,get()被添加到Hibernate的API中。差异是微不足道的:
如果load()无法在缓存或数据库中找到该对象,则抛出异常 。 load()方法永远不会返回null。如果找不到对象,则get()方法返回 。
load()方法可能会返回代理而不是实际的持久实例。 代理是一个占位符,它在第一次访问 时触发加载实际对象;另一方面,在( ),get()永远不会返回代理。 get()和load()之间的选择很简单:如果您确定存在持久对象 ,并且不存在将被视为例外,则load()是一个不错的选项。如果您不确定是否存在具有给定 标识符的持久实例,请使用get()并测试返回值以查看它是否为null。使用load()具有进一步的含义:应用程序可以检索到持久实例的有效引用(代理),而不触及数据库以检索其持久状态。因此, load()在缓存或数据库中未找到持久对象 时可能不会引发异常;当代理服务器 被访问时,将会抛出异常。 当然,通过标识符检索对象并不像使用任意的 查询那么灵活。
那么,至少在nhibernate中,session.Get(id)将从数据库中加载对象,而session.Load(id)只会在不离开服务器的情况下为其创建代理对象。与您的POCO(或POJO :)中的所有其他惰性加载属性一样。然后,您可以使用此代理作为对象本身的参考来创建关系等。
想象它有一个只保留Id的对象,如果你需要的话可以加载其余的对象。如果你只是通过它来创建关系(如FK),这个ID就是你所需要的。
session.load()将始终返回一个“代理”(Hibernate术语)而不会触及数据库。在Hibernate中,proxy是一个具有给定标识符值的对象,其属性尚未初始化,它看起来像是一个临时假对象。 如果未找到任何行,则会引发ObjectNotFoundException。
session.get()总是命中数据库并返回实际对象,这是一个表示数据库行的对象,而不是代理。 如果未找到任何行,则返回null。
这些方法的性能也使差异。在两个...
另外,我们必须小心,而使用负载,因为它会抛出一个异常,如果对象不存在。只有当我们确定物体存在时,我们才必须使用它。
使用“load”而不是“get”的一个间接结果是,使用版本属性进行乐观锁定可能无法像您期望的那样工作。如果加载只是创建代理并且不从数据库读取,则不会加载版本属性。该版本只会在/之后加载,如果以后引用该对象上的属性,则会触发选择。与此同时,另一个会话可以更新该对象,并且会话将不具有执行乐观锁定检查所需的原始版本 - 所以会话的更新将覆盖另一个会话的更新而不会发出警告。
下面试图勾画出这个场景,其中两个会话使用一个具有相同标识符的对象。在数据库对象最初的版本是10
Session 1 Session 2
--------- ---------
Load object
Wait a while..
Load object
Modify object property
[triggers db 'select' -
version read as 10]
Commit
[triggers db update,
version modified to 11]
Modify object property
[triggers db 'select' -
version read as 11]
Commit
[triggers db update,
version modified to 12]
实际上,我们希望会议1的提交失败,乐观锁定异常,但它会在这里取得成功。
使用“get”而不是“load”可以解决问题,因为get会立即发出select,并且版本号会在乐观锁定检查的正确时间加载。
还有一个额外的点::如果对象不在缓存以及对数据库中找到Hibernate的Session类的
get方法返回null。 while load()方法抛出ObjectNotFoundException,如果在缓存以及数据库上找不到对象,但永远不会返回null。
它总是会返回一个“代理”(休眠期)而无需访问数据库:
一个很好的说明从http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load()找到。
在Hibernate中,proxy是一个具有给定标识符值的对象,其属性尚未初始化,它只是看起来像一个临时假对象。
它将始终返回具有给定标识值的代理对象,即使标识值不存在于数据库中。但是,当您尝试通过从数据库中检索其属性来初始化代理时,它将使用select语句来访问数据库。如果找不到任何行,则会抛出ObjectNotFoundException。
session.get():
它总是碰到数据库(如果没有在缓存中找到)并返回真实对象,一个代表数据库行的对象,而不是代理。
如果未找到任何行,则返回null。
load()无法从缓存或数据库中找到该对象,抛出异常并且load()方法永远不会返回null。
如果找不到对象,则get()方法返回null。 load()方法可能会返回代理而不是实际的持久实例get()永远不会返回代理。
我正在调试一个问题,其中session.Get()正在返回代理! –
2010-03-29 15:03:03
非常感谢!对我来说,钱的一部分是:“如果load()无法在缓存或数据库中找到对象,则抛出异常。如果找不到对象,则get()方法返回null。” – Chris 2010-07-28 04:23:20