hibernate中的一级缓存与闪照区

首先Hibernate中的一级缓存默认是打开的,并且范围从session创建到session关闭,存储的数据必须是持久态的数据。

1 //从session创建开始,一级缓存也跟着创建
2 Session session = HibernateSessionFactory.getSession();
3 ...
4 //到session关闭,一级缓存  
5 session.close();

一级缓存的执行流程:

     如果现在需要获得一个数据库里面的账号为“980517”的用户,执行Java代码

1 User user = (User)session.get(User.class,"980517")

    这时底层并不是直接执行sql语句,而是先到缓存区去找,如果找不到账号为“980517”的用户,那么才会去执行sql语句,并把它放到缓存区中去,;如果在缓存区中找到了,就不会执行sql语句了(这就是优点:减少了操作数据库的次数),直接返回这个User对象。下面来粗略得看一看这部分的源码:

 1 //数据加载一般都是在doLoad中完成,不仅仅是get()这个方法        
 2 protected final T doLoad(Serializable id) {
 3             if ( this.lockOptions != null ) {//这个if就是去缓存区中去找,如果找到了,就带着数据直接return
 4                 LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this );
 5                 fireLoad( event, LoadEventListener.GET );
 6                 return (T) event.getResult();
 7             }
 8 
 9             LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this );
10             boolean success = false;
11             try {
12                 fireLoad( event, LoadEventListener.GET );
13                 success = true;
14             }
15             catch (ObjectNotFoundException e) {
16                 // if session cache contains proxy for non-existing object
17             }
18             finally {
19                 afterOperation( success );
20             }
21             return (T) event.getResult();
22         }

一级缓存的特性:持久态可以直接更新数据库。

    说这个特性之前提一个概念:快照区(副本,保留最开始的数据)

    比如上面的User,它不仅会在一级缓存区存一份,也会在快照区存一份,当对User这个对象执行set方法来改变它的属性时,缓存区会跟着修改,但是快照区不会修改,这就会出现不一致的情况。当程序最后执行commit()方法提交事务的时候,它会比较缓存区和快照区,如果快照区的数据(也就是最开始的数据)和一级缓存区的数据不一致时,他就会执行一个更新的操作来更新数据库。这就意味着我们可以用先get后set的方式来取代hibernate中update更新数据库的方式。

如果理解有误还请斧正,感谢。

 

posted @ 2019-11-03 11:41  洋气的豌豆  阅读(157)  评论(0编辑  收藏  举报