2017-09-10 65 views
4

我的印象是session.load()加载缓存中的代理对象,而session.get()总是碰到数据库,但在观看JavaBrains video后我感到困惑。休眠:在session.load的情况下急切和延迟加载vs session.get

根据这段视频,当我们调用下面的get方法时,它会在内存中加载代理对象UserDetails

user = (UserDetails) session.get(UserDetails.class, 1); 

UserDetails结构

enter image description here

虽然在注释部分,一个家伙说:

没有代理用户类,而不是代理对象 集合已创建。

现在有两个问题在这里。

1st:涉及session.load()和session.get()的取回策略和创建代理对象,这个问题已经由我回答。

第二种:在这种情况下,代理对象将为UserDetails或收集创建(仍有待回答)。

感谢

回答

2

我得到了答案here

  1. Hibernate默认会创建运行时代理。它将对象加载为代理,除非指定了获取模式或设置为false。 这就是为什么它总是创建一个对象的代理(如果我们使用get()或load()以及任何获取策略)无关紧要。

  2. get()首先在缓存中检查代理是否存在,如果不存在,它将触发数据库,​​同时在缓存中创建对象的代理并返回代理对象,一旦对象加载到缓存中,随后的下一个调用将执行可重复读取。

  3. load()总是检索代理对象。它从永久上下文缓存中读取数据,并且如果代理不存在于缓存中,它将返回null。

+0

是的,这正是我在评论中提到的。为了测试您的情况,为什么不在代码中尝试'session.clear()'并分析结果? 清除二级缓存,请阅读: https://dzone.com/articles/clearing-hibernate-second-leve –

+0

@Rahul,的确你是对的,如果你能回答第二个问题“在这个问题代理对象将创建UserDetails或收集?“ – Gaurav

1

这里,UserDetails是家长和Address是孩子。 Hibernate实际上是懒加载儿童Address。 因此,最终所有的子元素(在这种情况下为Address)在加载父元素(本例中为UserDetails)时未预先加载。

所以,当你这样做:

user = (UserDetails) session.get(UserDetails.class, 1); 

休眠没有实际加载的所有子(Collection<Address>)。 而是仅当您明确地访问它们时,Hibernate才会加载Address。所以休眠不会打DB的Address表,除非你真的需要它们,这就是延迟加载的目的。

这意味着通过延迟加载是什么,而你得到的UserDetails代理对象,它并不真正打Address表,除非您尝试显式访问集合元素。换句话说,您需要遍历集合进行休眠以获取Address表。

您可能会陷入每次为每个孩子敲击数据库(Address)的情况。因此,请拨打listOfAddresses.size()以便一次加载所有的孩子。

还要注意的是延迟加载将默认为发生一到多许多一对多箱子。

+0

我的问题实际上是关于在session.load()和session.get()的情况下获取策略和创建代理对象,而不仅仅是急切和懒惰的加载。 – Gaurav

+0

那么你必须明白'Load()'实现**延迟加载**和'get()'永远不会返回代理。 –

+0

@ Rahul,这就是为什么它加载代理对象的情况下get() – Gaurav

-1

2问题回答: 代理服务器的地址为您的问题上下文,您可以这么说。 深入或详细地说,第一个hibernate也会为userdetail创建代理,但只要查询命中,代理将有数据。但是,由于默认情况下hibernate是延迟加载,而Address是UserDetail中的子代,它将仅作为代理返回,并且您将只获得Address(主键值)的id值。 不要对代理服务器感到困惑。代理将为所有类的父类(UserDetail)或子类(Address)创建,但对于子类,它将只有id数据。

+0

我只想知道谁投下了这个票。你可以解释这里有什么问题。 –