Hibernate一级缓存的使用

PSR*_*PSR 3 java orm hibernate hibernate-cache

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

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

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

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

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

Adr*_*hum 5

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

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

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

Foo foo1 = session.get(Foo.class, 1L);
Foo foo2 = session.get(Foo.class, 1L);
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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


对于问题

它在会话中如何可用,直到我关闭它

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

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

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