Hibernate学习---第十五节:hibernate二级缓存

1、二级缓存所需要的 jar 包

这三个 jar 包实在 hibernate 解压缩文件夹的 lib\optional\ehcache 目录下

2、配置 ehcache.xml

<ehcache>

    <!-- 指定当缓存数据超出规定缓存大小的时候,超出的缓存数据写入到磁盘的位置 -->
    <diskStore path="D:/cache/tmp"/>
    <!--
        maxInMemory       - 允许在二级缓存中的持久化对象数量
        eternal           - 缓存中的持久化对象是否允许销毁  false:表示可以销毁
        timeToIdleSeconds - 当激活时间到期,持久化对象可以存活的时间(钝化时间)
        timeToLiveSeconds - 缓存中对象的激活时间(有效时间)
        overflowToDisk    - 是否允许缓存数据序列化到磁盘
    -->
    <defaultCache
        maxElementsInMemory="10"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
     />
</ehcache>

3、配置 hibernate.cfg.xml

在配置文件添加如下代码:

<property name="hibernate.cache.use_second_level_cache">true</property>

<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

具体如下:

<!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="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>
        <!-- 二级缓存配置   -->
        <!-- 开启二级缓存(默认是开启二级缓存的) -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!-- 配置二级缓存的视实现类(第三方插件包)  以下这个缓存类的包路径是错误的
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.internal.EhCacheRegionFactory</property> -->
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
        <mapping resource="learn\hibernate\bean\Person.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

4、支持二级缓存持久化类配置,有两种配置方式

第一种在持久化配置文件中配置:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="learn.hibernate.bean">
    <class name="Person" table="t_person">
        <!-- 配置持久化类支持二级缓存的读写操作 -->
        <cache usage="read-write"/>
        <id name="id" column="person_id">
            <generator class="native"/>
        </id>
        <property name="name" column="t_name"/>
        <property name="age"/>
        <property name="passwork"/>
        <property name="birthday"/>
    </class>
</hibernate-mapping>

第二种在 hibernate.cfg.xml 文件中配置:

<!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="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>
        <!-- 二级缓存配置   -->
        <!-- 开启二级缓存(默认是开启二级缓存的) -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!-- 配置二级缓存的视实现类(第三方插件包)  以下这个缓存类的包路径是错误的
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.internal.EhCacheRegionFactory</property> -->
        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
        <mapping resource="learn\hibernate\bean\Person.hbm.xml"/>
        <!--
            持久化类的二级缓存配置:
            1、在持久化类配置文件中配置  <cache usage="read-write"/>
            2、在 hibernate.cfg.xml 文件中配置,如下:(推荐)
         -->
        <class-cache usage="read-write" class="learn.hibernate.bean.Person"/>
    </session-factory>
</hibernate-configuration>

5、代码测试

/**
 * 在配置二级缓存的查询中步骤如下:
 * 先搜索   一级缓存------> 二级缓存  ------> SQL查询-------> 将数据写入缓存中
 * 二级缓存是可以在多个 session 中共享的
 * get()、load() 方法支持二级缓存的  读写  操作
 */
@Test
public void testQuery(){
    session = factory.openSession();
    Person p = (Person)session.get(Person.class, 1);
    System.out.println(p);
    session.close();
    System.out.println("-------------------");
    session = factory.openSession();
    Person p2 = (Person)session.get(Person.class, 1);
    System.out.println(p2);
    session.close();
}

/**
 * list() 方法支持二级缓存的写,不支持读
 */
@Test
public void testQuery2(){
    String hql = "from Person";

    session = factory.openSession();
    Query query = session.createQuery(hql);
    List<Person> list = query.list();
    for(Person p : list){
        System.out.println(p);
    }
    session.close();

    System.out.println("---------------------------");
    session = factory.openSession();
    Query query2 = session.createQuery(hql);
    List<Person> list2 = query2.list();
    for(Person p : list2){
        System.out.println(p);
    }
    session.close();

    System.out.println("---------------------------");
    session = factory.openSession();
    Person p = (Person)session.get(Person.class, 6);
    System.out.println(p);
    session.close();
}

/**
 * iterate() 方法支持二级缓存的写读操作
 */
@Test
public void testQuery3(){
    String hql = "from Person";

    session = factory.openSession();
    Query query = session.createQuery(hql);
    Iterator<Person> it = query.iterate();
    while(it.hasNext()){
        System.out.println(it.next());
    }
    session.close();

    System.out.println("---------------------------");
    session = factory.openSession();
    Query query2 = session.createQuery(hql);
    Iterator<Person> it2 = query2.iterate();
    while(it2.hasNext()){
        System.out.println(it2.next());
    }
    session.close();

    System.out.println("---------------------------");
    session = factory.openSession();
    Person p = (Person)session.get(Person.class, 6);
    System.out.println(p);
    session.close();
}

6、二级缓存的管理

/**
 * 二级缓存的管理
 *
 */
@Test
public void testQuery() throws InterruptedException{
    String hql = "from Person";

    session = factory.openSession();
    // 获得二级缓存的操作句柄(对象)
    Cache cache = factory.getCache();
    Query query = session.createQuery(hql);
    Iterator<Person> it = query.iterate();
    while(it.hasNext()){
        System.out.println(it.next());
    }
    System.out.println("--------------------------");
    // 判断缓存中是否存在该条数据
    boolean flag = cache.containsEntity(Person.class, 7);
    System.out.println(flag);
    // 将持久化类从缓存中剔除
    cache.evictEntity(Person.class, 7);
    // 将一个持久化类型从缓存中全部剔除
    cache.evictEntityRegion(Person.class);
    session.close();

}

7、验证超出规定数量的持久化对象会不会被写入到指定的目录下

package learn.hibernate.test;

import static org.junit.Assert.*;

import java.util.Iterator;
import java.util.List;

import learn.hibernate.bean.Person;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernate2 {

    SessionFactory factory = null;
    Session session = null;
    Transaction tx = null;

    /**
     * 测试之前初始化数据
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    @Before
    public void setUp() throws Exception {
        System.out.println("---------初始化数据----------");

        Configuration config = new Configuration().configure();
        ServiceRegistry sr = new ServiceRegistryBuilder()
        .applySettings(config.getProperties()).buildServiceRegistry();
        factory = config.buildSessionFactory(sr);
        //session = factory.openSession();
    }

    /**
     * 测试之后释放(销毁)数据
     * @throws Exception
     */
    @After
    public void tearDown() throws Exception {
        System.out.println("---------释放数据----------");
        /*if(session.isOpen()){
            session.close();
        }*/
    }

    /**
     * 测试缓存中的对象数量大于配置文件后,是否会将多余的对象写入到在磁盘上生成文件
     * 关闭  factory 是否会将磁盘文件释放删除
     * @throws InterruptedException
     */
    @Test
    public void testQuery() throws InterruptedException{
        String hql = "from Person";

        session = factory.openSession();
        Query query = session.createQuery(hql);
        Iterator<Person> it = query.iterate();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        session.close();
        System.out.println("--------sleep-start------");
        // 为了观察二级缓存序列化操作过程,让程序暂停短暂时间,观察磁盘文件是否生成
        Thread.sleep(10000);
        System.out.println("--------sleep-end------");
        factory.close();
    }
}

8、查询缓存

首先要做 hibernate.cfg.xml 文件中配置如下代码:

<property name="hibernate.cache.use_query_cache">true</property>

开启查询缓存,默认情况下查询缓存是关闭的;查询缓存是基于二级缓存的

测试:

/**
 * 只有 list() 支持查询缓存,其他的方法不支持
 * 查询缓存的生命周期是很短暂的,即便查询条件的值发生变化也会重新查询
 *
 */
@Test
public void testQuery2(){
    String hql = "from Person";

    session = factory.openSession();
    Query query = session.createQuery(hql);
    /**
     * 启动查询缓存
     * 告诉 hibernate 先到查询缓存中搜索有没有相同的查询语句查询过,有就将之前的查询结果直接返回
     */
    query.setCacheable(true);
    List<Person> list = query.list();
    for(Person p : list){
        System.out.println(p);
    }
    session.close();

    System.out.println("---------------------------");
    session = factory.openSession();
    Query query2 = session.createQuery(hql);
    // 如果查询没有变,那么接下来的查询结果将从上一次的查询中获取
    query2.setCacheable(true);
    query2.setCacheable(true);
    List<Person> list2 = query2.list();
    for(Person p : list2){
        System.out.println(p);
    }
    session.close();
}

9、hibernate 的优化

(1)、使用 Configuration 装载映射文件时,不要使用绝对路径装载。最好的方式是通过 getResourceAsStream() 装载映射文件,这样 hibernate 会从 classpath 中寻找已配置的映射文件。

(2)、SessionFactory 的创建非常消耗资源,整个应用一般只要一个 SessionFactory 就够了,只有多个数据库的时候才会使用多个 SessionFactory。

(3)、在整个应用中,Session 和事务应该能够统一管理。(Spring 为 Hibernate 提供了很好的支持)

(4)、将所有的集合属性配置设为懒加载(lazy=true)

(5)、在定义关联关系时,集合首选 Set,如果集合中的实体存在重复,则选择 List(定义配置文件时,可以将 List定义为 idbag),数组的性能最差。

(6)、在一对多的双向关联中,一般将集合的 inverse 属性设置为 true,让集合的对方维护关联关系。例如:Person-Address,由 Address 来维护 Person 和 Address 的关联关系。

让拥有外键的一端来进行关联关系的维护比较好

(7)、在执行更新的时候尽量配置 dynamic-update=”true”,表示没有修改的属性不参与更新操作

(8)、HQL 子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分

(9)、如果可以,使用乐观锁代替悲观锁

(10)、如果要很好的掌握 Hibernate,熟练掌握关系数据理论和 SQL 是前提条件

时间: 2024-10-09 17:13:09

Hibernate学习---第十五节:hibernate二级缓存的相关文章

Hibernate学习---第十四节:hibernate之session线程安全

1.hibernate.cfg.xml 文件中添加如下代码开启线程安全: <property name="hibernate.current_session_context_class">thread</property> 具体如下: <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http

Hibernate学习---第十三节:hibernate过滤器和拦截器的实现

一.hibernate 过滤器 1.在持久化映射文件中配置过滤器,代码如下: <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-

python学习第十五节(正则)

正则的贪婪匹配 非贪婪模式按照最小重复数取 非贪婪匹配 正则的方法 re.split 正则分割 分割次数 保留分隔符,用一个括号套住分隔符 sub 替换字符串需要三个参数,要替换的内容(正则),新内容,字符串 分开写用compile可以写一次规则然后多次匹配,好处就是方便灵活. 返回一个迭代器对象 爬虫爬豆瓣电影信息,用正则 模块 configparser功能:创建成下面类型的文件 使用方法 读操作 DEFAULT是默认信息,不需要打印,默认信息是所有段落信息的共享信息. 用上图方法判断字段是否

《Hibernate学习笔记十》:多对多关联关系详解

<Hibernate学习笔记十>:多对多关联关系 前面介绍了一对一.多对一和一对多的关联关系在Hibernate应如何实现,这篇博文就来介绍下最后一种关联关系:多对多.多对多关联关系在我们现实生活中的例子实在是太多太多,最典型的就是老师和学生的例子:一个老师可以教多个学生,而一个学生又可以被多个老师来教. 了解一点数据库的我们都知道,在数据库中表示多对多的关联关系,是借助于中间表来解决的. 如下: 还是和以往的思路一样,每一种关联关系都分为单向关联和双向关联,我们每种都会进行介绍,对于单向和双

《Hibernate学习笔记十二》学生、课程、分数关系的设计与实现

<Hibernate学习笔记十二>学生.课程.分数关系的设计与实现 这个马士兵老师的Hibernate视频学习的一个题目,这里面要用到多对多.多对一的关联关系以及联合主键,因此觉得挺好的,自己写篇博文来记录下. 先考虑数据库表 1.学生表:为简单起见,只考虑了学生id和学生姓名,其中id为主键 2.课程表:为简单起见,只考虑了课程id和课程名称,其中id为主键 3.分数表 分数表有两种解决方案 3.1 第一种为:使用联合主键:student_id 和 course_id 3.2 第二种:不使用

JPA学习(五、JPA_二级缓存)

框架学习之JPA(五) JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. Sun引入新的JPA ORM规范出于两个原因:其一,简化现有Java EE和Java SE应用开发工作:其二,Sun希望整合ORM技术,实现天下归一. 学习视频:尚硅谷框架jpa学习(有兴趣的同学留言邮箱) 使用软件:eclipse Java版本:jdk8 本节目录 五.JPA_二级缓存 1.添

hbase 学习(十五)缓存机制以及可以利用SSD作为存储的BucketCache

下面介绍Hbase的缓存机制: a.HBase在读取时,会以Block为单位进行cache,用来提升读的性能 b.Block可以分类为DataBlock(默认大小64K,存储KV).BloomBlock(默认大小128K,存储BloomFilter数据).IndexBlock(默认大小128K,索引数据,用来加快Rowkey所在DataBlock的定位) c.对于一次随机读,Block的访问顺序为BloomBlock.IndexBlock.DataBlock,如果Region下面的StoreFi

javascript基础学习(十五)

javascript之cookie 学习要点: cookie介绍 创建与获取cookie cookie的编码 cookie的生存期 cookie的路径 cookie的domain cookie的secure 一.cookie介绍 cookie实际上就是一些信息,这些信息以文件的形式存储在客户端计算机上.在javascript中,cookie主要用来保存状态,或用于识别身份. 二.创建与获取cookie 创建cookie的语法代码如下所示:document.cookie="name=value&q

centos lamp/lnmp阶段复习 第二十五节课

centos  lamp/lnmp阶段复习   第二十五节课 上半节课 下半节课 f