Hibernate的缓存机制如何应用?

来源:互联网 发布:女生长得像男生知乎 编辑:程序博客网 时间:2024/06/05 06:03

2.一级缓存应用: save()。当session对象调用save()方法保存一个对象后,该对象会被放入到session的缓存中。 get()和load()。当session对象调用get()或load()方法从数据库取出一个对象后,该对象也会被放入到session的缓存中。 使用HQL和QBC等从数据库中查询数据。

复制代码
public class Client{    public static void main(String[] args)    {        Session session = HibernateUtil.getSessionFactory().openSession();        Transaction tx = null;        try        {            /*开启一个事务*/            tx = session.beginTransaction();            /*从数据库中获取id="402881e534fa5a440134fa5a45340002"的Customer对象*/            Customer customer1 = (Customer)session.get(Customer.class, "402881e534fa5a440134fa5a45340002");            System.out.println("customer.getUsername is"+customer1.getUsername());            /*事务提交*/            tx.commit();                        System.out.println("-------------------------------------");                        /*开启一个新事务*/            tx = session.beginTransaction();            /*从数据库中获取id="402881e534fa5a440134fa5a45340002"的Customer对象*/            Customer customer2 = (Customer)session.get(Customer.class, "402881e534fa5a440134fa5a45340002");            System.out.println("customer2.getUsername is"+customer2.getUsername());            /*事务提交*/            tx.commit();                        System.out.println("-------------------------------------");                        /*比较两个get()方法获取的对象是否是同一个对象*/            System.out.println("customer1 == customer2 result is "+(customer1==customer2));        }        catch (Exception e)        {            if(tx!=null)            {                tx.rollback();            }        }        finally        {            session.close();        }    }}
复制代码
复制代码
结果Hibernate:     select        customer0_.id as id0_0_,        customer0_.username as username0_0_,        customer0_.balance as balance0_0_     from        customer customer0_     where        customer0_.id=?customer.getUsername islisi-------------------------------------customer2.getUsername islisi-------------------------------------customer1 == customer2 result is true
复制代码

输出结果中只包含了一条SELECT SQL语句,而且customer1 == customer2 result is true说明两个取出来的对象是同一个对象。其原理是:第一次调用get()方法, Hibernate先检索缓存中是否有该查找对象,发现没有,Hibernate发送SELECT语句到数据库中取出相应的对象,然后将该对象放入缓存中,以便下次使用,第二次调用get()方法,Hibernate先检索缓存中是否有该查找对象,发现正好有该查找对象,就从缓存中取出来,不再去数据库中检索。

 

3.二级缓存的管理:

evict(Class arg0, Serializable arg1)将某个类的指定ID的持久化对象从二级缓存中清除,释放对象所占用的资源。

sessionFactory.evict(Customer.class, new Integer(1));  

evict(Class arg0)  将指定类的所有持久化对象从二级缓存中清除,释放其占用的内存资源。

sessionFactory.evict(Customer.class);  

evictCollection(String arg0)  将指定类的所有持久化对象的指定集合从二级缓存中清除,释放其占用的内存资源。

sessionFactory.evictCollection("Customer.orders");  

 

4.二级缓存的配置

常用的二级缓存插件

EHCache  org.hibernate.cache.EhCacheProvider

OSCache  org.hibernate.cache.OSCacheProvider

SwarmCahe  org.hibernate.cache.SwarmCacheProvider

JBossCache  org.hibernate.cache.TreeCacheProvider

复制代码
<!-- EHCache的配置,hibernate.cfg.xml --> <hibernate-configuration>    <session-factory>       <!-- 设置二级缓存插件EHCache的Provider类-->       <property name="hibernate.cache.provider_class">          org.hibernate.cache.EhCacheProvider       </property>       <!-- 启动"查询缓存" -->       <property name="hibernate.cache.use_query_cache">          true       </property>    </session-factory>  </hibernate-configuration>
复制代码
复制代码
<!-- ehcache.xml --><?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <!--
        缓存到硬盘的路径
   
-->
    <diskStore path="d:/ehcache"></diskStore>
    <!--
        默认设置
        maxElementsInMemory : 在內存中最大緩存的对象数量。
        eternal : 缓存的对象是否永远不变。
        timeToIdleSeconds :可以操作对象的时间。
        timeToLiveSeconds :缓存中对象的生命周期,时间到后查询数据会从数据库中读取。
        overflowToDisk :内存满了,是否要缓存到硬盘。
   
-->
    <defaultCache maxElementsInMemory="200" eternal="false"
        timeToIdleSeconds
="50" timeToLiveSeconds="60" overflowToDisk="true"></defaultCache>
    <!--
        指定缓存的对象。
        下面出现的的属性覆盖上面出现的,没出现的继承上面的。
   
-->
    <cache name="com.suxiaolei.hibernate.pojos.Order" maxElementsInMemory="200" eternal="false"
        timeToIdleSeconds
="50" timeToLiveSeconds="60" overflowToDisk="true"></cache>
</ehcache>
复制代码
复制代码
<!-- *.hbm.xml --><?xml version="1.0" encoding='UTF-8'?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" ><hibernate-mapping>   <class>       <!-- 设置该持久化类的二级缓存并发访问策略 read-only read-write nonstrict-read-write transactional-->       <cache usage="read-write"/>       </class></hibernate-mapping>
复制代码

若存在一对多的关系,想要在在获取一方的时候将关联的多方缓存起来,需要在集合属性下添加<cache>子标签,这里需要将关联的对象的hbm文件中必须在存在<class>标签下也添加<cache>标签,不然Hibernate只会缓存OID。

复制代码
<hibernate-mapping>        <class name="com.suxiaolei.hibernate.pojos.Customer" table="customer">            <!-- 主键设置 -->            <id name="id" type="string">                <column name="id"></column>                <generator class="uuid"></generator>            </id>                        <!-- 属性设置 -->            <property name="username" column="username" type="string"></property>            <property name="balance" column="balance" type="integer"></property>                        <set name="orders" inverse="true" cascade="all" lazy="false" fetch="join">                <cache usage="read-only"/>                <key column="customer_id" ></key>                <one-to-many class="com.suxiaolei.hibernate.pojos.Order"/>            </set>                    </class>    </hibernate-mapping>