Hibernate:session.get和session.load之间的区别

时间:2009-03-04 01:36:58

标签: hibernate proxy hibernate-session

从API中,我可以看到它与代理有关。但我找不到很多关于代理的信息,也不理解调用session.getsession.load之间的区别。有人可以解释或指导我参考页面吗?

谢谢!

8 个答案:

答案 0 :(得分:115)

来自Hibernate forum

  

这来自Hibernate in Action一书。好的人读了这个..


按标识符检索对象 以下Hibernate代码段从数据库中检索User对象:

User user = (User) session.get(User.class, userID);

get()方法很特殊,因为标识符唯一标识一个 一个类的实例。因此,应用程序通常将标识符用作 方便处理持久对象。按标识符检索可以使用缓存 检索对象时,如果对象已被缓存,则避免数据库命中。 Hibernate还提供了load()方法:

User user = (User) session.load(User.class, userID);

load()方法较旧;由于用户,get()被添加到Hibernate的API中 请求。差别很小:

如果load()无法在缓存或数据库中找到对象,则会出现异常 抛出。 load()方法永远不会返回null。 get()方法返回 如果找不到该对象,则返回null。

load()方法可能返回代理而不是真正的持久化实例。 代理是一个占位符,可以触发真实对象的加载 第一次访问;在 另一方面,get()永远不会返回代理。 在get()和load()之间选择很简单:如果你确定持久性 对象存在,不存在将被视为异常,load()是a 不错的选择。如果您不确定是否存在给定的持久实例 标识符,使用get()并测试返回值以查看它是否为null。使用load()有 进一步暗示:应用程序可以检索到的有效引用(代理) 持久化实例,无需访问数据库即可检索其持久状态。所以 load()在找不到持久对象时可能不会抛出异常 在缓存或数据库中;当代理时,异常将被抛出 被访问。 当然,通过标识符检索对象不像使用任意一样灵活 查询。

答案 1 :(得分:14)

好吧,至少在nhibernate中,session.Get(id)将从数据库加载对象,而session.Load(id)只创建一个代理对象而不离开你的服务器。与POCO(或POJO :)中的所有其他延迟加载属性一样工作。然后,您可以使用此代理作为对象本身的引用来创建关系等。

将其视为拥有一个只保留Id的对象,如果您需要它将加载其余的对象。如果你只是传递它来创建关系(比如FK),那么id就是你所需要的。

答案 2 :(得分:9)

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

session.get()始终命中数据库并返回真实对象,一个表示数据库行的对象,而不是代理。     如果找不到行,则返回null。

使用这些方法的性能也会产生差异。两个人之间...

答案 3 :(得分:3)

再多一点::

获取Hibernate的方法如果在缓存和数据库中找不到对象,则Session类返回null。 如果在高速缓存和数据库上找不到对象但从不返回null,则load()方法抛出ObjectNotFoundException。

答案 4 :(得分:2)

使用“load”而不是“get”的一个间接后果是使用版本属性的乐观锁定可能无法正常工作。如果加载只是创建代理并且不从数据库读取,则不加载版本属性。只有当/稍后引用对象上的属性,触发选择时才会加载版本。与此同时,另一个会话可以更新对象,并且您的会话将不具有进行乐观锁定检查所需的原始版本 - 因此会话的更新将覆盖其他会话的更新而不会发出警告。

这是尝试用两个会话处理具有相同标识符的对象来勾勒出这个场景。 DB中对象的初始版本为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,并且版本号将在正确的时间加载以进行乐观锁定检查。

答案 5 :(得分:0)

此外,我们在使用load时必须小心,因为如果对象不存在,它将抛出异常。只有当我们确定对象存在时,我们才必须使用它。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

如果找不到对象,则

get()方法返回null。 load()方法可能返回代理而不是真正的持久化实例get()永远不会返回代理。