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

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

谢谢!!

从Hibernate论坛 :

这从书中的hibernate行动。 好的一个读这个..


通过标识符检索对象以下Hibernate代码片段从数据库中检索用户对象:

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

get()方法是特殊的,因为标识符唯一标识了一个类的单个实例。 因此,应用程序通常使用标识符作为持久对象的便捷句柄。 通过标识符检索可以在检索对象时使用高速caching,如果对象已被高速caching,则避免数据库命中。 Hibernate也提供了一个load()方法:

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

load()方法比较旧; 由于用户请求,get()被添加到Hibernate的API中。 差异是微不足道的:

如果load()在caching或数据库中找不到对象,则会抛出exception。 load()方法永远不会返回null。 如果找不到对象,则get()方法返回null。

load()方法可能会返回一个代理,而不是真正的持久化实例。 代理是一个占位符,当第一次被访问时触发真实对象的加载; 另一方面,get()永远不会返回代理。 get()和load()之间的select很简单:如果您确定持久对象存在,并且不存在将被视为exception,则load()是一个不错的select。 如果您不确定是否存在具有给定标识符的持久实例,请使用get()并testing返回值以查看它是否为null。 使用load()还有一个含义:应用程序可以检索一个有效的引用(一个代理)到一个持久化的实例,而不用敲打数据库来检索它的持久化状态。 所以load()可能不会在caching或数据库中find持久对象时抛出exception; 当访问代理时,将会抛出exception。 当然,通过标识符检索对象不如使用任意查询那么灵活。

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

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

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

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

这些方法的性能也使差异。 两个之间…

另外一个加点:

获取Hibernate的方法如果在caching以及数据库中找不到对象,则会话类将返回null。 而load()方法抛出ObjectNotFoundException如果在caching以及数据库上找不到对象,但永远不会返回null。

使用“load”而不是“get”的一个间接结果是使用版本属性的乐观locking可能无法像您期望的那样工作。 如果一个负载只是创build一个代理而不从数据库中读取,那么version属性不会被加载。 只有当/如果以后引用对象上的某个属性时才会加载该版本,从而触发一个select。 与此同时,另一个会话可以更新对象,而您的会话将不具有它需要执行乐观locking检查的原始版本 – 所以会话的更新将覆盖其他会话的更新,而不会发出警告。

这里试图通过两个使用相同标识符的对象来描述这个场景。 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的提交失败,并出现一个乐观的lockingexception,但是它会在这里成功。

使用“get”而不是“load”可以解决问题,因为get会立即发出一个select,并且版本号会在正确的时间被加载,以进行乐观locking检查。

另外我们在使用load的时候要小心,因为如果对象不存在,它将会抛出一个exception。 只有当我们确定对象存在时,我们才能使用它。

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

load()无法从caching或数据库中find对象,抛出exception并且load()方法永远不会返回null。

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