简体   繁体   English

使用Hibernate一级缓存

[英]Use of Hibernate first level cache

It looks simple question .I tried a lot understand but failed. 这看起来很简单。我尝试了很多但是失败了。

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一级缓存意味着会话级缓存。当我们在同一个会话中多次检索同一个对象时,它将从Cache中检索。

For example I have an Employee record with id 100 in database. 例如,我在数据库中有一个ID为100的Employee记录。

I opened a session and get that employee object.Until I close session that object is available in the same session. 我打开一个会话并获取该员工对象。直到我关闭该对象在同一会话中可用的会话。

Question:Why I need to retrieve same object more than once in same session(Any how it is available in session until I close it)? 问题:为什么我需要在同一个会话中多次检索同一个对象(在我关闭它之前,它是如何在会话中可用的)?

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一级缓存意味着会话级缓存。当我们在同一个会话中多次检索同一个对象时,它将从Cache中检索。

It is half-correct. 它是半正确的。 Apart from what you said, one major reason for first level cache is, under same session, Hibernate will ensure same entity (entity with same ID) is going to be represented by same object instance. 除了你所说的,第一级缓存的一个主要原因是,在同一会话下,Hibernate将确保相同的实体(具有相同ID的实体)将由相同的对象实例表示。

What you said is correct only if you are getting the entity from session by ID: 只有当您通过ID从会话中获取实体时,您所说的才是正确的:

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

First call of get() will go to DB to load Foo . 第一次调用get()将转到DB加载Foo When 2nd call is invoked, Hibernate will check if within this session, any Foo with ID 1 has already been retrieved. 当调用第二个调用时,Hibernate将检查在此会话中是否已检索到任何ID为1的Foo As it has been retrieved before, Hibernate will simply get that Foo instance and return to you. 正如之前检索过的那样,Hibernate将简单地获取Foo实例并返回给您。

However, this scenario is not the most common situation that you will see first level cache in effect. 但是,这种情况并不是最常见的情况,您将看到第一级缓存生效。 Consider this: 考虑一下:

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

(Assuming the above finders are internally running query thru Hibernate session) When Hibernate run the 2nd query, internally Hibernate is running the SQL, get the resultset, and convert each record to a User. (假设上面的查找程序在内部运行查询通过Hibernate会话)当Hibernate运行第二个查询时,内部Hibernate运行SQL,获取结果集,并将每个记录转换为用户。 Assuming one of the active users is having ID 777. When Hibernate construct that User object instance, it will first check if it exists in first level cache. 假设其中一个活动用户具有ID 777.当Hibernate构造该User对象实例时,它将首先检查它是否存在于第一级缓存中。 Because it was previously retrieved (in previous query which find by user name), instead of constructing a new User object instance, Hibernate will simply reuse the instance that previously constructed (and stored in 1st level cache) and use it in the result list. 因为它先前已被检索(在先前的查询中通过用户名查找),而不是构造新的User对象实例,Hibernate将简单地重用先前构建的实例(并存储在第一级缓存中)并在结果列表中使用它。

By doing so, Hibernate can ensure, within the same session, if you retrieve same entity (same class with same ID) by different ways, you can always assume that entity will be same object instance. 通过这样做,Hibernate可以在同一个会话中确保如果您通过不同的方式检索相同的实体(具有相同ID的相同类),您可以始终假设该实体将是相同的对象实例。

Think of a more complicated example, that you are trying to retrieve Order s from your system, which refers to User (assume Many-To-One). 想想一个更复杂的例子,你试图从你的系统中检索Order s,它指的是User (假设是Many-To-One)。 What you will discover is, different Order , whenever it refers to same User (in DB), it is actually referring to same User object instance. 您将发现的是,不同的Order ,每当它引用同一个User (在DB中)时,它实际上是指同一个User对象实例。


For the question of 对于这个问题

how it is available in session until I close it 在关闭它之前它是如何在会话中提供的

it is more an internal implementation detail of Hibernate. 它更像是Hibernate的内部实现细节。 However, conceptually, you can imagine it as, each Session is internally having a Map, the key is Entity Type + ID, the value is the entity object instance. 但是,从概念上讲,你可以想象它,每个Session内部都有一个Map,关键是Entity Type + ID,值是实体对象实例。

When you query from DB and when session construct the entities for you, for each entity, it will lookup from the map if it is already there. 当您从数据库查询并且会话为您构建实体时,对于每个实体,它将从地图中查找它是否已存在。 If not, session will construct the entity and put in the map. 如果没有,会话将构造实体并放入地图。 If it is already there, session will simply make use of the entity in the map 如果已经存在,则会话将仅使用地图中的实体

Similar idea when you are getting entity by ID (thru Session.get() or Session.load() etc) 当您通过ID(通过Session.get()Session.load()等获取实体)时的类似想法

You don't need to retrieve the same object several times from the EntityManager, but if you do, you'll get the same object. 你并不需要从EntityManager的访问同一对象多次,但如果你这样做,你会得到相同的对象。 This is what caching is about. 这就是缓存的意义所在。 As to your second question: The EntityManager keeps a reference to this object and returns it if you ask for the same object again. 至于你的第二个问题:EntityManager保留对这个对象的引用,如果再次请求同一个对象,则返回它。

I'd recommend working through a JPA tutorial like http://docs.oracle.com/javaee/6/tutorial/doc/bnbpz.html . 我建议使用像http://docs.oracle.com/javaee/6/tutorial/doc/bnbpz.html这样的JPA教程。 IMHO, you should be focusing on learning JPA and view Hibernate simply as a JPA provider. 恕我直言,你应该专注于学习JPA并简单地将Hibernate视为JPA提供者。

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

It depends how do you manage Session or EntityManager . 这取决于您如何管理SessionEntityManager If it is created per request, you won't need to query it again. 如果是按请求创建的,则无需再次查询。 But if Session / EntityManager is reused then the same object can be retrieved several times so it will be returned from the First level cache. 但是如果重用Session / EntityManager则可以多次检索同一个对象,以便从第一级缓存返回。

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

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