Hibernate一级缓存的使用

Use of Hibernate first level cache

看起来很简单的问题。我尝试了很多理解但失败了。

据我所知,Hibernate 一级缓存意味着会话级别 cache.When 我们在同一会话中多次检索同一对象,它将从缓存中检索。

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

我打开了一个会话并得到了那个员工object.Until我关闭了那个对象在同一个会话中可用的会话。

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

不需要多次从 EntityManager 检索同一个对象,但如果这样做,您将获得同一个对象。这就是缓存的意义所在。关于你的第二个问题:EntityManager 保留对此对象的引用,如果你再次请求相同的对象,returns它。

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

如果在需要检索此员工对象的地方进行了后续调用,则可以从同一会话中获取,而不是从数据库中获取

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

As per my knowledge Hibernate first level cache means session level cache.When we retrieve the same object more than once in same session it will retrieve from Cache.

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

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

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

get() 的第一次调用将转到数据库以加载 Foo。当调用第二次调用时,Hibernate 将检查在此会话中是否已检索到 ID 为 1 的任何 Foo。正如之前检索到的那样,Hibernate 将简单地获取 Foo 实例和 return 给你。

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

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

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

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

想想一个更复杂的例子,你正试图从你的系统中检索 Orders,它指的是 User(假设多对一)。你会发现,不同的 Order,每当它引用相同的 User(在数据库中)时,它实际上指的是相同的 User 对象实例。


对于

的问题

how it is available in session until I close it

它更多的是 Hibernate 的内部实现细节。不过从概念上,你可以想象成,每个Session内部都有一个Map,key是Entity Type+ID,value是实体对象实例。

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

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