(五)Hibernate一级缓存

一、简介

缓存,介于应用程序和永久数据存储源之间,作用是为了降低应用程序对物理数据源访问的频率,从而提高应用的运行性能。 
例如我们cpu执行效率每秒处理的数据高达上千兆,而我们的硬盘读取速度却没那么高,读取几百兆,这时候我们使用缓存来存储数据,存储满后一次性交由cpu处理。

Hibernate中也存在缓存,同样是为了提高效率。Hibernate的缓存包括Session的缓存和SessionFactory的缓存。

Session的缓存是内置的,不能被卸载,也被称为Hibertnate的一级缓存。

SessionFactory有一个内置缓存和外置缓存。SessionFactory的外置缓存是一个可配置的缓存插件。默认情况下,Hibernate不会启用这个缓存插件。被称为Hibernate的二级缓存。

二、缓存范围

事务范围:缓存只能被当前事务访问。一级缓存是Session的缓存,Session对象生命周期通常对应一个事务,因此是事务范围的缓存。

进程范围:缓存被进程内的所有事务共享。二级缓存是可配置的缓存插件,由SessionFactory管理,SessionFactory生命周期和应用程序的进程对应,因此是进程范围的缓存。

集群范围:在集群环境中,缓存被同一个机器或者多个机器上的多个进程共享。

三、Session缓存

Session缓存是Hibernate的一级缓存。Session对象中具有一个缓存。Session的缓存是一块内存空间,存放的是持久化对象。

当Session通过save方法持久化一个对象时,该对象被加入到Session缓存中。 
当Session通过get方法获取一个持久化对象时,Session会先判断Session缓存中是否存在这个对象,如果存在,就不需要再从数据库中查找。

========我们来测试一下缓存的存在==============

        //开启事务
        Transaction ts=session.beginTransaction();
        //加上断点,当我们执行完这一步,会打印select语句,而后面的都不会打印,说明并没有从数据库中获取
        User user1=session.get(User.class, 5);
        //这次get方法会先从session缓存中查找,由于已经存在,直接返回引用
        User user2=session.get(User.class, 5);
        User user3=session.get(User.class, 5);
        System.out.println(user1==user2);//true
        System.out.println(user1==user3);//true
        session.close();

四、脏检查及清理缓存的机制

我们先来看下面的例子

        Transaction ts=session.beginTransaction();
        User user1=session.get(User.class, 5);
        user1.setName("swaggy");
        ts.commit();

 

我们发现我们改变了Name属性,这时候session缓存中的对象的name属性和数据库表中的NAME字段不一致了。但是我们并没有进行更新操作,而是直接提交了事务

幸运的是,Session中在清理缓存的时候,会自动进行脏检查。如果发现Session缓存中的持久化对象和数据库中的记录不一致,就会根据对象的最新属性去更新数据库。 
所以在本例中,Session会自动提交一个update语句对数据库进行更新。

(1)Session是怎样进行脏检查的呢?

当一个对象被加入到Sesion缓存中时,Session会为该对象复制一份快照。当Session清理缓存时,会比较当前对象的属性和快照来判断是否发生变化,如果发生变化,就会根据最新属性来执行相关的更新操作。

我们看下面一个例子加深对快照的理解

 

//我们从数据库中取出 id为5,name为tom,password为123456的对象
        Transaction ts=session.beginTransaction();
        User user1=session.get(User.class, 5);
        session.update(user1);
        session.close(); 

        过程:获取了持久化对象,放入缓存中,并创建了快照,我们执行更新,Session缓存中的对象会和快照进行比较,没有任何变化,所以不会执行update语句。
  //我们自己设置一个和数据库中一模一样的对象,这时候会打印update语句
        Transaction ts=session.beginTransaction();
        User user=new User();
        user.setId(5);
        user.setName("tom");
        user.setPassword("123456");
        session.update(user);
        ts.commit();
        session.close();

        过程:因为此时我们执行update语句时会将对象直接放入缓存中,但是没有持久化对象的快照,所以进行对比结果就是不一致,所以尽管什么都没更改,还是会执行update语句,在控制台打印。

(2)什么时候会清理缓存呢?

-默认情况下,在调用commit()方法时会先清理缓存。再向数据库提交事务。 

-当执行查询操作时,如果缓存中的持久化对象属性已经发生了改变,就会先清理缓存,同步数据,保证查询到的是正确的结果。 

-当应用程序显式调用Session的flush()方法时  

-Session清理缓存的例外情况,如果对象使用的是native生成策略生成OID,那么调用Session的save()方法来保存该对象时,会立刻执行向数据库的插入语句。

  

(3)如果不希望Session在以上默认的时间点清理缓存,可以通过Session的setFlushMode()方法来设定清理缓存的时间点。
FlushMode类定义了三种清理模式。

                            各种查询方法          commit()方法        flush()方法
-FlushMode.AUTO(默认模式)        清理                 清理                清理
-FlushMode.COMMIT              不清理                清理                清理
-FlushMode.NEVER               不清理                不清理              清理   

例如Session.setFlushMode(FlushMode.AUTO)

  

 

五、Session接口的其他API

--Session的save()和persist()方法
        两个方法都是用来保存对象,能把临时状态转变为持久化状态。 

    两个方法的区别在于:
    save方法持久化对象时,会返回持久化对象的OID。所以程序执行save时会立刻执行insert语句,来返回数据库生成的OID。 

    persist方法持久化对象时,不会保证立即为持久化对象的OID赋值,不会立即生成insert语句,而是有可能在Session清理缓存时才为OID赋值。

--Session的clear()方法
    清空一级缓存 

--Session的update方法
                    update()方法可以将游离对象转变为持久化对象。用来执行修改操作。
                    update()方法完成以下操作
                    -把游离对象加入到当前缓存中,变为持久化对象
                    -然后计划执行update语句

                    只要通过update使游离对象转变为持久化对象,即使没有修改任何属性,在清理缓存时还是会执行update语句。
                    如果希望Session仅当修改了属性时才执行update语句,可以在映射文件中的<class>元素中设置select-before-update="true",默认为false
                    这样当Session清理缓存时,会先发送一条查询语句,然后判断缓存中的对象和记录是否一致,不一致才执行update语句。

                    当update()方法将游离对象转变为持久化对象时,如果Session缓存中已经存在相同的OID持久化对象,那么会抛出异常。
                    例如:
                        Transaction ts=session.beginTransaction();
                        User user1=session.get(User.class, 5);
                        session.evict(user1);
                        User user2=session.get(User.class, 5);
                        session.update(user1);
                        ts.commit();

                        因为Session的缓存是一个Map结构,OID为key,对象为value。
                        当执行session的update方法时,由于缓存中已经存在了OID为5的持久化对象,因此会抛出异常。 

-Session的saveOrUpdate()方法 

            Session的saveOrUpdate()方法同时包含了save()和update()方法的功能
            如果传入的参数是临时对象(OID为null),就调用save方法。
            如果传入的参数是游离对象(OID不为null),就执行update方法。

  

 

  

  

原文地址:https://www.cnblogs.com/yuexiaoyun/p/9452207.html

时间: 2024-11-12 02:30:58

(五)Hibernate一级缓存的相关文章

hibernate 一级缓存和二级缓存

hibernate一级缓存:session缓存即事务级缓存,session关闭,缓存自动销毁,开发人员不用管理,由hibernate管理,save.update.saveoOrUpdate.lock.load.list会自动向一级缓存中存放数据,get,load,list会自动从一级缓存中取数据,可调用evict(Object object)和clear()清除缓存. hibernate二级缓存:sessionFactory缓存即进程级别缓存,由缓存插件实现,如OSCache,对hibernat

(10)Hibernate一级缓存

1.为什么要用缓存? 目的:减少对数据库的访问次数!从而提升hibernate的执行效率! 2.Hibernate中缓存分类 一级缓存.二级缓存 3.一级缓存的概念 1)Hibenate中一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数!  只在session范围有效! Session关闭,一级缓存失效! 2)当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session的缓存中

转载 hibernate一级缓存和二级缓存的区别

文章来源:http://blog.csdn.net/defonds/article/details/2308972     hibernate一级缓存和二级缓存的区别 缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 缓存的介质一般是内存,所以读写速度很快.但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质.

Hibernate一级缓存(补)

------------------siwuxie095 什么是缓存 缓存是介于应用程序和永久性数据存储源(如:硬盘上的文件 或 数据库) 之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提 高应用的运行性能 针对数据库,则: 数据是存到数据库中的,而数据库本身也是文件系统,使用流方式操作文 件的效率并不是很高 如果把数据存到内存里面,不需要使用流方式,就可以直接读取内存中的 数据,提高读取的效率 Hibernate 缓存 1.Hibernate 框架中提供了很多优化方式,Hibe

hibernate一级缓存,二级缓存和查询缓存

一级缓存 (必定存在)  session里共享缓存,伴随session的生命周期存在和消亡: 1. load查询实体支持一级缓存 2. get查询实体对象也支持 3. save保存的实体对象会缓存在一级缓存 4. clear evict会清除session缓存 5. save巨大数据,每20个数据,一般flush执行sql将数据持久化然后clear缓存,防止内存溢出,save放最后. 6. iterate使用一级缓存(creatQuery中的查询实体对象list会使用一级缓存,查询对象实体属性不

hibernate 一级缓存

一级缓存 为什么要用缓存? 目的:减少对数据库的访问次数!从而提升hibernate的执行效率! Hibernate中缓存分类: 一级缓存 二级缓存 概念 1)Hibenate中一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数!  只在session范围有效! Session关闭,一级缓存失效! 2)当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session的缓存中. 3)S

[转] Hibernate一级缓存、二级缓存

缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 缓存的介质一般是内存,所以读写速度很快.但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质.缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期. hibernate的缓存包括Session的缓存和SessionFactory的缓

hibernate一级缓存和二级缓存的区别

缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 缓存的介质一般是内存,所以读写速度很快.但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质.缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期. Hibernate的缓存包括Session的缓存和SessionFactory的缓

Hibernate一级缓存和二级缓存深度比较

1.什么是缓存 缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 缓存的介质一般是内存,所以读写速度很快.但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质.缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期. Hibernate的一级缓存是内置的,不能被卸载. Hiberna