Hibernate的二级缓存

一、概述

    Hibernate包括两个级别的缓存:默认总是启用的Session级别的一级缓存和可选的SessionFactory级别的二级缓存。

    其中,Session级别的一级缓存默认总是有效的,当应用保存持久化实体、修改持久化实体时,Session并不会立即把这种改变flush到数据库,而是缓存在当前Session的一级缓存中,除非程序显式调用Session的flush方法,或程序关闭Session时把变些改变flush到底层数据库。通过这种缓存,可以减少与数据库的交互,从而提高数据访问性能。

    SessionFactory级别的二级缓存是全局性的,应用的所有Session都共享这个二级缓存。程序的二级缓存必须显式开启。一旦在应用中开启了二级缓存,当Session需要抓取数据时,Session将会优先从二级缓存抓取。从而提高应用的数据库访问性能。

二、开启二级缓存

1. 配置hibernate.cfg.xml(开启二级缓存,设置二级缓存的实现类)

<?xml version="1.0" encoding="GBK"?>
<!-- 指定Hibernate配置文件的DTD信息 -->
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate- configuration是连接配置文件的根元素 -->
<hibernate-configuration>
    <session-factory>
        <!-- 指定连接数据库所用的驱动 -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 指定连接数据库的url,hibernate连接的数据库名 -->
        <property name="connection.url">jdbc:mysql://localhost/aaa</property>
        <!-- 指定连接数据库的用户名 -->
        <property name="connection.username">root</property>
        <!-- 指定连接数据库的密码 -->
        <property name="connection.password">root</property>
        <!-- 指定连接池里最大连接数 -->
        <property name="hibernate.c3p0.max_size">20</property>
        <!-- 指定连接池里最小连接数 -->
        <property name="hibernate.c3p0.min_size">1</property>
        <!-- 指定连接池里连接的超时时长 -->
        <property name="hibernate.c3p0.timeout">5000</property>
        <!-- 指定连接池里最大缓存多少个Statement对象 -->
        <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">true</property>
        <!-- 指定数据库方言 -->
        <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
        <!-- 显示Hibernate持久化操作所生成的SQL -->
        <property name="show_sql">true</property>
        <!-- 将SQL脚本进行格式化后再输出 -->
        <property name="hibernate.format_sql">true</property>
        
        <!-- 开启二级缓存 -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!-- 设置缓存提供者 -->
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        
        <!-- 开启二级缓存的统计功能 -->
        <property name="hibernate.generate_statistics">true</property>
        <!-- 设置使用结构化方式来维护缓存项 -->
        <property name="hibernate.cache.use_structured_entries">true</property>
    
        <!-- 指定根据当前线程来界定上下文相关Session -->
        <property name="hibernate.current_session_context_class">thread</property>
        <!-- 罗列所有的映射文件 -->
        <mapping resource="test/Person.hbm.xml"/>
        <mapping resource="test/Address.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

2. 添加所需jar包

    将Hibernate lib下optional中对应的缓存JAR包(ehcache),comons-logging,backport-util-concurrent导入到项目。

3. 配置ehcache.xml

<?xml version="1.0" encoding="GBK"?>
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <!-- maxElementsInMemory设置缓存中最多可放多少个对象,
      eternal设置缓存是否永久有效,
      timeToIdleSeconds设置缓存的对象多少秒没有被使用就会清理掉
      timeToLiveSeconds设置缓存的对象在过期之前可以缓存多少秒
      diskPersistent设置缓存是否被持久化到硬盘中,路径由<diskStore.../>元素指定
      -->
    <defaultCache maxElementsInMemory="10000" eternal="false" overflowToDisk="true"
     timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>
</ehcache>

4. 为实体启用二级缓存

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test">
    <class name="Person" table="person_inf">
        <!-- 指定Person启用缓存,而且设置的缓存策略为只读 -->
        <cache usage="read-only"/>
        <id name="id" column="id">
            <generator class="identity"/>
        </id>
        <property name="name" type="string"/>
    </class>
</hibernate-mapping>

5. 测试

package test;

import java.util.List;
import java.util.Map;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class TestPerson {

    public static void main(String[] args) {
        Configuration conf = new Configuration().configure();
        SessionFactory sf = conf.buildSessionFactory();
        // 创建第一个Session
        Session sess = sf.openSession();
        Transaction tx = sess.beginTransaction();
        List list = sess.createQuery("from Person p").list();
        tx.commit();
        // 创建第二个Session
        Session sess2 = sf.getCurrentSession();
        sess2.beginTransaction();
        // 根据主键加载实体,系统将直接从二级缓存读取,因此不会发出查询的SQL语句
        Person p = (Person) sess2.load(Person.class, 1);
        System.out.println(p.getName());
        sess2.getTransaction().commit();
        
        //----------统计二级缓存,得到二级缓存的内容----------
        //二级缓存的名字默认与持久化类的类名相同
        Map cacheEntries = sf.getStatistics().getSecondLevelCacheStatistics("test.Person").getEntries();
        System.out.println(cacheEntries);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值