繁体   English   中英

休眠:session.load 与 session.get

[英]Hibernate: session.load vs session.get

我的印象是session.load()在缓存中加载代理对象,而session.get()总是命中数据库,但在观看 JavaBrains视频后我感到困惑。

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

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

UserDetails结构是

在此处输入图片说明

在评论区,有网友评论道:

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

现在这里有两个问题。

第一:在 session.load() 和 session.get() 的情况下与获取策略和创建代理对象相关,我在下面回答了这个问题。

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

谢谢

1.Fetching Strategies:在 session.get 或 session.load ( https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch20. html#performance-fetching-lazy )。

2. Session.get:从不返回 proxy ,根据 hibernate 文档:( https://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/Session.html#get(java.lang.类,java.io.Serializable))

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

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

3. Session.load:根据休眠文档:

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

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

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

这里, UserDetails是父级, Address是子级。 Hibernate 实际上是延迟加载子Address 因此,最终在加载父元素(在本例中为UserDetails )时,不会预加载所有子元素(在本例中为Address )。

所以,当你这样做时:

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

Hibernate 实际上并未加载所有子项( Collection<Address> )。 而是 Hibernate 仅在您显式访问它们时加载Address 因此,除非您确实需要它们,否则 Hibernate 不会为Address表命中 DB,这就是延迟加载的目的。

延迟加载意味着当您获得UserDetails的代理对象时,除非您尝试显式访问 Collection 元素,否则它不会真正命中Address表。 换句话说,您需要遍历 Hibernate 的集合以获取Address表。

您可能会陷入每次为每个孩子( Address )访问数据库的情况。 因此,显式调用listOfAddresses.size()以便一次加载所有子项。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM