繁体   English   中英

使用Hibernate一级缓存

[英]Use of Hibernate first level cache

这看起来很简单。我尝试了很多但是失败了。

据我所知,Hibernate一级缓存意味着会话级缓存。当我们在同一个会话中多次检索同一个对象时,它将从Cache中检索。

例如,我在数据库中有一个ID为100的Employee记录。

我打开一个会话并获取该员工对象。直到我关闭该对象在同一会话中可用的会话。

问题:为什么我需要在同一个会话中多次检索同一个对象(在我关闭它之前,它是如何在会话中可用的)?

据我所知,Hibernate一级缓存意味着会话级缓存。当我们在同一个会话中多次检索同一个对象时,它将从Cache中检索。

它是半正确的。 除了你所说的,第一级缓存的一个主要原因是,在同一会话下,Hibernate将确保相同的实体(具有相同ID的实体)将由相同的对象实例表示。

只有当您通过ID从会话中获取实体时,您所说的才是正确的:

Foo foo1 = session.get(Foo.class, 1L);
Foo foo2 = session.get(Foo.class, 1L);

第一次调用get()将转到DB加载Foo 当调用第二个调用时,Hibernate将检查在此会话中是否已检索到任何ID为1的Foo 正如之前检索过的那样,Hibernate将简单地获取Foo实例并返回给您。

但是,这种情况并不是最常见的情况,您将看到第一级缓存生效。 考虑一下:

// psuedo code only
User user = findByUserName("ADRIAN");  // assume ID = 777
List<User> users = findAllActiveUsers();

(假设上面的查找程序在内部运行查询通过Hibernate会话)当Hibernate运行第二个查询时,内部Hibernate运行SQL,获取结果集,并将每个记录转换为用户。 假设其中一个活动用户具有ID 777.当Hibernate构造该User对象实例时,它将首先检查它是否存在于第一级缓存中。 因为它先前已被检索(在先前的查询中通过用户名查找),而不是构造新的User对象实例,Hibernate将简单地重用先前构建的实例(并存储在第一级缓存中)并在结果列表中使用它。

通过这样做,Hibernate可以在同一个会话中确保如果您通过不同的方式检索相同的实体(具有相同ID的相同类),您可以始终假设该实体将是相同的对象实例。

想想一个更复杂的例子,你试图从你的系统中检索Order s,它指的是User (假设是Many-To-One)。 您将发现的是,不同的Order ,每当它引用同一个User (在DB中)时,它实际上是指同一个User对象实例。


对于这个问题

在关闭它之前它是如何在会话中提供的

它更像是Hibernate的内部实现细节。 但是,从概念上讲,你可以想象它,每个Session内部都有一个Map,关键是Entity Type + ID,值是实体对象实例。

当您从数据库查询并且会话为您构建实体时,对于每个实体,它将从地图中查找它是否已存在。 如果没有,会话将构造实体并放入地图。 如果已经存在,则会话将仅使用地图中的实体

当您通过ID(通过Session.get()Session.load()等获取实体)时的类似想法

你并不需要从EntityManager的访问同一对象多次,但如果你这样做,你会得到相同的对象。 这就是缓存的意义所在。 至于你的第二个问题:EntityManager保留对这个对象的引用,如果再次请求同一个对象,则返回它。

我建议使用像http://docs.oracle.com/javaee/6/tutorial/doc/bnbpz.html这样的JPA教程。 恕我直言,你应该专注于学习JPA并简单地将Hibernate视为JPA提供者。

如果后续调用需要检索此员工对象,则可以从同一会话获取,而不是从DB获取

这取决于您如何管理SessionEntityManager 如果是按请求创建的,则无需再次查询。 但是如果重用Session / EntityManager则可以多次检索同一个对象,以便从第一级缓存返回。

暂无
暂无

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

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