Hibernate二级缓存

          1)Hibernate一级缓存

                 session即为Hibernate的一级缓存,其中缓存的数据随着session的关闭而消失。因而从缓存角度讲session作为一级缓存对性能的提升不大。(当然session的主要作用不是作为缓存,而是用来管理对象,持久化状态的对象的变化可以更新到数据库中)

factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();

Department department = (Department) session.load(Department.class, 2l);
System.out.println(department.getName());
session.close();

session = factory.openSession();

Department department2 = (Department) session.load(Department.class, 2l);
System.out.println(department2.getName());
session.close();
             结果为:

Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
develope
Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
develope

            说明session关闭后其中缓存的数据也消失了,所以虽然第二次查询的是同样的数据,但是还是去查询数据库了。

          2)配置二级缓存

              1. 导入jar

<dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-ehcache</artifactId>
     <version>4.3.6.Final</version>
</dependency>
             2. 修改hibernate.cfg.xml文件

                 基础配置:

<!-- 表示是否开启二级缓存,默认为false -->
<property name="hibernate.cache.use_second_level_cache">true</property> 
<!-- 指定使用的二级缓存 -->
<property name="hibernate.cache.region.factory_class">
     org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
<!-- 指定EHCache的配置文件 -->
<property name="hibernate.cache.provider_configuration_file_resource_path">  
    ehcache.xml  
</property> 
             说明哪些类需要使用缓存

<class-cache usage="read-write" class="cn.com.cpf.pojo.Department"/>

            3.ehcache.xml中配置

<ehcache>  
  <!--如果缓存中的对象存储超过指定的缓存数量的对象存储的磁盘地址(文件夹)-->  
  <diskStore path="D:/ehcache"/>  
  
  <!-- 默认cache:如果没有对应的特定区域的缓存,就使用默认缓存 -->  
  <defaultCache maxElementsInMemory="10000"  
                eternal="false"  
                timeToIdleSeconds="300"   
                timeToLiveSeconds="600"  
                overflowToDisk="false"/>  //开启则表示如果超过缓存数量则写入到硬盘中
  </cache>  
</ehcache> 
            4. 执行如上代码,结果为:

Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
develope
develope
              只查询了一次数据库,说明二级缓存已经起作用
        3)具有如下特征的数据适合放入二级缓存中

              1.很少被修改的数据

              2.不是很重要的数据,允许偶尔出现并发的数据

              3.常量数据

        4) 具有如下特征的数据不适合放入二级缓存中

              1.经常被修改的数据

              2.非常重要(如财务数据),决不允许出现并发操作的数据

        5)Hibernate中 缓存分类

               1.类缓存

                   1>配置方法

                        hibernate.cfg.xml中

<class-cache usage="read-write" class="cn.com.cpf.pojo.Department"/>
                  2>工作原理

                      使用一个Map将对象id作为key,对象作为value。查询的时候现根据id查找一级缓存,一级缓存中没有则查找二级缓存,也没有则查询数据库

                 3>注意

                    因为是根据id来查找的,所以通过get、load这种根据id查找的方式才可以使用缓存,使用hql这种方式一定会查数据库
             2.集合缓存

                  1>配置方法

                   hibernate.cfg.xml中

<class-cache usage="read-write" class="cn.com.cpf.pojo.Employee"/>
<collection-cache usage="read-write" collection="cn.com.cpf.pojo.Department.employees"/>
                  必须将集合属性和对应类全被指定才行,少一个都不会使用二级缓存

                 2>实例

                   pojo:

public class Department {
       private Long id;
       private String name;
       private Set<Employee> employees = new HashSet<Employee>();
        ..............
}
               Department.hbm.xml
 <class name="cn.com.cpf.pojo.Department"   table="t_department" lazy="true">
  <id name="id" column="id">
     <generator class="native"/>
  </id>
  <property name="name"/>
  
  <set name="employees" inverse="false" lazy="true">
     <key column="departmentId"/>
      <one-to-many class="cn.com.cpf.pojo.Employee" />
  </set>
 </class>
            hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
    <property name="connection.driver_class">
       com.mysql.jdbc.Driver
    </property>
    <property name="connection.url">
       jdbc:mysql://localhost:3306/test
    </property>
    <property name="connection.username">root</property>
    <property name="connection.password">12345</property>

    <property name="dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <property name="connection.isolation">2</property>

    <!-- 表示是否开启二级缓存,默认为false -->
    <property name="hibernate.cache.use_second_level_cache">true</property> 
      <!-- 指定使用的二级缓存 -->
    <property name="hibernate.cache.region.factory_class">
         org.hibernate.cache.ehcache.EhCacheRegionFactory
    </property>
      <!-- 指定EHCache的配置文件 -->
      <property name="hibernate.cache.provider_configuration_file_resource_path">  
         ehcache.xml  
      </property>  

	<property name="show_sql">true</property>
	<property name="hibernate.hbm2ddl.auto">update</property>


        <property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
        <property name="hibernate.c3p0.max_size">2</property> 
        <property name="hibernate.c3p0.min_size">2</property> 
        <property name="hibernate.c3p0.timeout">5000</property> 
        <property name="hibernate.c3p0.max_statements">100</property> 
        <property name="hibernate.c3p0.idle_test_period">3000</property> 
        <property name="hibernate.c3p0.acquire_increment">2</property> 
        <property name="hibernate.c3p0.validate">false</property> 

	<mapping resource="cn/com/cpf/pojo/Department.hbm.xml"/>
	<mapping resource="cn/com/cpf/pojo/Employee.hbm.xml"/>
	
	<class-cache usage="read-write" class="cn.com.cpf.pojo.Department"/>
	<class-cache usage="read-write" class="cn.com.cpf.pojo.Employee"/>
	<collection-cache usage="read-write" collection="cn.com.cpf.pojo.Department.employees"/>
</session-factory>
</hibernate-configuration>
             测试代码:

factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Department department = (Department) session.load(Department.class, 2l);
System.out.println(department.getName());
System.out.println(department.getEmployees());
session.close();

session = factory.openSession();
Department department2 = (Department) session.load(Department.class, 2l);
System.out.println(department.getName());
System.out.println(department2.getEmployees());
session.close();
           结果为:

Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
develope
Hibernate: select employees0_.departmentId as departme3_3_0_, employees0_.id as id1_4_0_, employees0_.id as id1_4_1_, employees0_.name as name2_4_1_, employees0_.departmentId as departme3_4_1_ from t_employee employees0_ where employees0_.departmentId=?
[cn.com.cpf.pojo.Employee@7ccc8469, cn.com.cpf.pojo.Employee@57094981]
develope
[cn.com.cpf.pojo.Employee@7e0e03d0, cn.com.cpf.pojo.Employee@4a1c8d57]
           第二次查询时候没有查询数据库,说明二级缓存生效了
          如果在hibernate.cfg.xml中去掉对Employee类使用二级缓存的声明,即

<class-cache usage="read-write" class="cn.com.cpf.pojo.Department"/>
<collection-cache usage="read-write" collection="cn.com.cpf.pojo.Department.employees"/>
        再执行测试代码,结果为:

Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
develope
Hibernate: select employees0_.departmentId as departme3_3_0_, employees0_.id as id1_4_0_, employees0_.id as id1_4_1_, employees0_.name as name2_4_1_, employees0_.departmentId as departme3_4_1_ from t_employee employees0_ where employees0_.departmentId=?
[cn.com.cpf.pojo.Employee@54be8c3e, cn.com.cpf.pojo.Employee@29e965e9]
develope
Hibernate: select employee0_.id as id1_4_0_, employee0_.name as name2_4_0_, employee0_.departmentId as departme3_4_0_ from t_employee employee0_ where employee0_.id=?
Hibernate: select employee0_.id as id1_4_0_, employee0_.name as name2_4_0_, employee0_.departmentId as departme3_4_0_ from t_employee employee0_ where employee0_.id=?
[cn.com.cpf.pojo.Employee@58dcdffc, cn.com.cpf.pojo.Employee@fbb8694]
          可以看出在第二次访问类中集合的时候仍然访问了数据库,而且针对每一个对象都根据id访问了一次数据库。

         原因:仅对collection属性做了缓存,那么Hibernate二级缓存只会缓存collection中的id,第二次查询的时候,从缓存里面仅仅能查询出来id,所以就根据这个id分别查询了。
            3. 查询缓存

              1>说明:不管是类缓存还是集合缓存,都是缓存的id,所以无法使用hql。要使用查询缓存,那么就需要使用查询语句作为key,对象作为value保存
              2>配置

               在hibernate.cfg.xml中添加配置

<property name="cache.use_query_cache">true</property>
             3>使用

factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();

List<Department> departments = (List<Department>) session//
					.createQuery("FROM Department where id<3")//
					.setCacheable(true)//
					.list();

session.close();
session = factory.openSession();
List<Department> departments2 = (List<Department>) session//
					.createQuery("FROM Department where id<3")//
					.setCacheable(true)//
					.list();
session.close();
                结果为:

Hibernate: select department0_.id as id1_3_, department0_.name as name2_3_ from t_department department0_ where department0_.id<3
             只有一条sql,说明二级缓存已经起作用了
               4>注意

                  在使用hql查询的时候,需要调用setCacheable方法,并在配置文件中设置了使用查询缓存才会使用缓存

             Query或Criteria接口查询时设置其setCacheable(true): 
             默认的如果不在程序中显示的执行查询缓存声明操作,Hibernate是不会对查询的list进行缓存的。 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值