Hibernate一级缓存,二级缓存

来源:互联网 发布:什么是农村淘宝服务站 编辑:程序博客网 时间:2024/04/28 13:07
1、Hibernate的一级缓存

在Hibernate框架内部应用缓存提高应用系统的运行性能,Hibernate中的缓存分为为一级和二级缓存。

Hibernate 的一级缓存是内置缓存,不能通过程序代码或者配置人为取消取消,并且一级缓存通过Session对象实现缓存,所以也被为“Session”缓存。一级缓 存是事务级别的缓存,事务结束缓存中的所有数据失效。使用一级缓存可以在一个事务中减少查询和更新数据表的操作。如在一个事务中即使多次地修改一个持久对 象,但在提交事务之时,Hibernate只会执行一个update子句更新数据库的数据,更新的数据包括事务提交之前所有的修改内容。

2、一级缓存的实现原理

在 底层实现上,可以把一级缓存想象为Session对象维护一个Map对象,其中保存当前Session对象使用的数据。通过Session对象读取数据 时,该对象会首先依据要加载对象的类型和标识符属性查找这个Map对象中是否已经加载过这个持久化对象。如果找到,则直接返回这个对象;否则从数据库中查 询,加载数据后同时会把这个持久化对象保存在Map对象中。

3、管理一级缓存

管理一级缓存包括以下几种方法:

(1)、使用evict()方法从缓存中移除对象
  不能取消一级缓存的使用,但是可以使用Session的evict()方法从一级缓存中移除缓存的持久对象,同时该对象的状态会从持久化状态转换为托管状态。如:

 public void testRemoveL1Cache(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        Product p = (Product)session.get(Product.class, 1);
        //移除一级缓存中的Product对象
        session.evict(p);
        
        Product p2 = (Product)session.get(Product.class, 1);
        System.out.println(p==p2);
        tx.commit();
        session.close();
    }


程序的执行结果如下:

Hibernate: select product0_.id as id3_0_, product0_.name as name3_0_, product0_.price as price3_0_, product0_.description as descript4_3_0_ from tb_product product0_ where product0_.id=?

Hibernate: select product0_.id as id3_0_, product0_.name as name3_0_, product0_.price as price3_0_, product0_.description as descript4_3_0_ from tb_product product0_ where product0_.id=?

false

说明一级缓存中的对象被移除后,Hibernate只能从数据库中加载,同时加载后的对象与原来的对不再是同一个对象。

(2)、使用clear()方法从缓存中清除所有对象。

  用法如下:

    public void testRemoveAllL1Cache(){
        
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        Product p1 = (Product)session.get(Product.class, 1);
        Product p2 = (Product)session.get(Product.class, 2);
        //清除所有对象
        session.clear();
        
        Product p3 = (Product)session.get(Product.class, 1);
        Product p4 = (Product)session.get(Product.class, 2);
        
        System.out.println(p1==p3);
        System.out.println(p2==p4);
        tx.commit();
        session.close();
    }

程序执行结果如下:

Hibernate: select product0_.id as id3_0_, product0_.name as name3_0_, product0_.price as price3_0_, product0_.description as descript4_3_0_ from tb_product product0_ where product0_.id=?

Hibernate: select product0_.id as id3_0_, product0_.name as name3_0_, product0_.price as price3_0_, product0_.description as descript4_3_0_ from tb_product product0_ where product0_.id=?

Hibernate: select product0_.id as id3_0_, product0_.name as name3_0_, product0_.price as price3_0_, product0_.description as descript4_3_0_ from tb_product product0_ where product0_.id=?

Hibernate: select product0_.id as id3_0_, product0_.name as name3_0_, product0_.price as price3_0_, product0_.description as descript4_3_0_ from tb_product product0_ where product0_.id=?

false

false

(3)、使用Session对象的contains()、flush()和setReadOly()方法

 Session对象的contains()方法判断指定的对象是否缓存在一级缓存中,flush()方法刷新(同步)一级缓存中的数据,使其与数据库中的数据保存一致,setReadOnly()方法设置某个持久化对象为只读对象,而只读对象不执行脏数据检查。
 
 
 
 
 
 
 
 
 
 
 
Hiberante3 一级缓存总结
1.             Session 级别的缓存,它同 session邦定。它的生命周期和 session相同。 Session消毁,它也同时消毁;管理一级缓存,一级缓存无法取消,用两个方法管理, clear(),evict()
2.             两个 session 不能共享一级缓存,因它会伴随 session的生命周期的创建和消毁;
3.             Session缓存是实体级别的缓存,就是只有在查询对象级别的时候才使用,如果
使用 HQL和 SQL是查询属性级别的,是不使用一级缓存的!切记!!!!
4 .  iterate 查询使用缓存,会发出查询 Id的 SQL和 HQL语句,但不会发出查实体的,
它查询完会把相应的实体放到缓存里边,一些实体查询如果缓存里边有,就从缓存中查询,但还是会发出查询 id的 SQL和 HQL语句。如果缓存中没有它会数据库中查询,然后将查询到的实体一个一个放到缓存中去,所以会有 N+1问题出现。
5 . List() 和 iterate 查询区别:
使用iterate,list查询实体对象*N+1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题
所谓的N+1是在查询的时候发出了N+1条sql语句1:首先发出一条查询对象id列表的sqlN:
根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句list和iterate的区别?
list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据
iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题
6.Get()和load(),iterate方法都会使用一级缓存.  
7.hiberate3 session 存储过程如下:
       例如 object 对象
       Session.save(object);
       这时候不会把数据放到数据库,会先放到session缓存中去,数据库中没有相应记录,session.flush();才发SQL和HQL语句,数据库中有了相应记录,
       但是数据库用select 查不到,这是跟数据库事物级别有关系 .
 
       Session.beginTrransaction().commit();
       事物提交后 可以查询到了。

Session.flush()语句但是为什么不写呢,因为commit()会默认调用flush();

Hiberante3 二级缓存总结
1. Hibernate3的( sessionFactory)二级缓存和 session级别的缓存一样都只对实体对象做缓存,不对属性级别的查询做缓存;二级缓存的生命周期和 sessionFactory的生命周期是一样的, sessionFactory可以管理二级缓存;
2. sessionFactory级别的缓存,需要手动配置;所有的 session可以共享 sessionFactory 级别的缓存;(一般把一些不经常变化的实体对象放到 sessionFactory级别的缓存中,适合放不经常变化的实体对象。)
3. Hiberante3二级缓存的配置和使用方法如下:
1. 必须把 ehcache.jar包导入,然后到 Hibernate3.2的 etc文件下把 ehcache.xml复制到工程 src目录下(ehcache.xml里边的参数里边有详细英文说明);
(说明: ehcache.jar是第三方法的缓存产品, hiberante只是把它做了集成,还有好多第三方 hibernate集成的缓存产品,相关说明请查阅 hiberante3开发手册; ehcache是不支持分布应用的,如果有分布式需求,请换成支持分布式的二级缓存产品, hiberate3开发手册都有相头说明。配置方法都类似);
4. Hibernate3的二级缓存默认是开起的,也可以指定开起。在 hibernate.cfg.xml 文件下配置如下:
*修改 hibernate.cfg.xml文件,开户二级缓存;
                     <property name=”hibernate.cache.use_second_level_cache”>true</property>
                     *指定二级缓存产品的提供商;
<property name=”hibernate.cache.provider_class”>org.hibernate.cache.EhCacheProvider
</property>
要让那些实体使用二级缓存,在 hibernate.cfg.xml配置文件中加入:
<!—
让这个实体用二级缓存  也可以在实体中映射文件去配置即:
<cache usage="read-only"/>
-->
<class-cache class=”com.zzz.hibernate.ClassT” usage=”read-only”/>
Read-only一般使用这个策略,其它的 hibernate3开发手册中也有详细介绍;
CacheMode去 hibernate3开发手册中搜索这个关键字,可以找到一级缓存和二级缓存交互使用的问题;
 


0 0
原创粉丝点击