2009-03-04 67 views

回答

111

Hibernate forum

这从本书在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()在缓存或数据库中未找到持久对象 时可能不会引发异常;当代理服务器 被访问时,将会抛出异常。 当然,通过标识符检索对象并不像使用任意的 查询那么灵活。

+1

我正在调试一个问题,其中session.Get ()正在返回代理! – 2010-03-29 15:03:03

+7

非常感谢!对我来说,钱的一部分是:“如果load()无法在缓存或数据库中找到对象,则抛出异常。如果找不到对象,则get()方法返回null。” – Chris 2010-07-28 04:23:20

14

那么,至少在nhibernate中,session.Get(id)将从数据库中加载对象,而session.Load(id)只会在不离开服务器的情况下为其创建代理对象。与您的POCO(或POJO :)中的所有其他惰性加载属性一样。然后,您可以使用此代理作为对象本身的参考来创建关系等。

想象它有一个只保留Id的对象,如果你需要的话可以加载其余的对象。如果你只是通过它来创建关系(如FK),这个ID就是你所需要的。

9

session.load()将始终返回一个“代理”(Hibernate术语)而不会触及数据库。在Hibernate中,proxy是一个具有给定标识符值的对象,其属性尚未初始化,它看起来像是一个临时假对象。 如果未找到任何行,则会引发ObjectNotFoundException。

session.get()总是命中数据库并返回实际对象,这是一个表示数据库行的对象,而不是代理。 如果未找到任何行,则返回null。

这些方法的性能也使差异。在两个...

0

另外,我们必须小心,而使用负载,因为它会抛出一个异常,如果对象不存在。只有当我们确定物体存在时,我们才必须使用它。

1

使用“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,并且版本号会在乐观锁定检查的正确时间加载。

2

还有一个额外的点::如果对象不在缓存以及对数据库中找到Hibernate的Session类的

get方法返回null。 while load()方法抛出ObjectNotFoundException,如果在缓存以及数据库上找不到对象,但永远不会返回null。
它总是会返回一个“代理”(休眠期)而无需访问数据库:

0

一个很好的说明从http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load()找到。
在Hibernate中,proxy是一个具有给定标识符值的对象,其属性尚未初始化,它只是看起来像一个临时假对象。
它将始终返回具有给定标识值的代理对象,即使标识值不存在于数据库中。但是,当您尝试通过从数据库中检索其属性来初始化代理时,它将使用select语句来访问数据库。如果找不到任何行,则会抛出ObjectNotFoundException。
session.get():
它总是碰到数据库(如果没有在缓存中找到)并返回真实对象,一个代表数据库行的对象,而不是代理。
如果未找到任何行,则返回null。

0

load()无法从缓存或数据库中找到该对象,抛出异常并且load()方法永远不会返回null。

如果找不到对象,则get()方法返回null。 load()方法可能会返回代理而不是实际的持久实例get()永远不会返回代理。

相关问题