hibernate中的一级缓存与闪照区

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

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

一级缓存的执行流程:

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

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

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

//数据加载一般都是在doLoad中完成,不仅仅是get()这个方法        
protected final T doLoad(Serializable id) {
            if ( this.lockOptions != null ) {//这个if就是去缓存区中去找,如果找到了,就带着数据直接return
                LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this );
                fireLoad( event, LoadEventListener.GET );
                return (T) event.getResult();
            }

            LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this );
            boolean success = false;
            try {
                fireLoad( event, LoadEventListener.GET );
                success = true;
            }
            catch (ObjectNotFoundException e) {
                // if session cache contains proxy for non-existing object
            }
            finally {
                afterOperation( success );
            }
            return (T) event.getResult();
        }

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

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

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

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

相关推荐