Hibernate:session.load vs session.get

时间:2017-09-10 19:29:22

标签: java hibernate persistence

我的印象是session.load()将代理对象加载到缓存中,而session.get()总是访问数据库,但在看了JavaBrains video之后我很困惑。

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

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

UserDetails的结构是

enter image description here

在评论部分,一个人评论道:

  

没有User类的代理,而是代理对象的   集合已创建。

现在有两个问题。

  

1st:与session.load()和session.get()的获取策略和代理对象的创建有关,我已经在下面回答过。

     

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

由于

3 个答案:

答案 0 :(得分:6)

1.获取策略:在session.get或session.load(https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch20.html#performance-fetching-lazy)的工作中获取策略没有任何效果。

<强> 2。 Session.get: 永不返回代理, 根据hibernate文档:(https://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/Session.html#get(java.lang.Class,java.io.Serializable))

  

返回给定实体类的持久实例和给定标识符,如果没有这样的持久实例,则返回null。 (如果实例已与会话关联,则返回该实例。此方法永远不会返回未初始化的实例。)

意味着get方法首先检查缓存是否存在fully initialize object如果是,则返回该对象,否则为hits the database to get the object,并在将其保存在缓存空间后返回相同的内容。

第3。 Session.load:根据hibernate docs:

  

返回具有给定标识符的给定实体类的持久化实例,假设该实例存在。当访问非标识符方法时,此方法可能会返回按需初始化的代理实例。

意味着load方法首先检查缓存,如果fully initialize object存在,如果是,则返回该对象,否则返回代理(代理是委托给另一个对象的类。最初,当它没有被初始化,它只包含主键。当你调用一个方法时,就像Javadoc所说的那样,它通过`假设那个实例,通过从数据库加载实际实体,以及委托给这个加载的实体)来初始化存在。

注意:重要的是要注意load方法never throw an exception。如果您尝试检索任何其他属性而不是主键,您将获得ObjectNotFoundException来自代理对象。因为它会命中数据库从那里加载对象,这是不存在的。

答案 1 :(得分:2)

此处,UserDetails是父,Address是孩子。 Hibernate实际上是懒惰加载孩子Address。 因此,最终所有子元素(在这种情况下为Address)在加载父元素时都不会预先加载(在这种情况下为UserDetails)。

所以,当你这样做时:

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

Hibernate实际上并未加载所有子项(Collection<Address>)。 相反,只有在您明确访问它们时,Hibernate才会加载Address。因此,除非你真的需要它们,否则hibernate不会在Address表中找到数据库,这是延迟加载的目的。

延迟加载的含义是,当您获得UserDetails的代理对象时,除非您尝试明确访问Collection元素,否则它不会真正触及Address表。换句话说,您需要遍历hibernate的集合以获取Address表。

您可能会遇到每次为每个孩子(Address)点击数据库的情况。因此,请进行显式调用listOfAddresses.size(),以便一次加载所有子项。

另请注意,一对多多对多情况下,默认情况下会发生延迟加载

答案 2 :(得分:-1)

2 Ques Ans: 代理将是您可以说的问题上下文的地址。 在深度或细节上,首先hibernate也将为userdetail创建代理,但是一旦查询命中该代理就会有数据。但是由于hibernate默认是延迟加载而Address是UserDetail中的子节点,它将仅作为代理返回,并且您将只获得Address(主键值)的id值。 不要对代理感到困惑。将为所有类(父类(UserDetail)或子类(Address))创建代理,但对于子类,它将只具有id数据。