Java笔记之hibernate(十二):一级缓存和二级缓存

0.说在前面

  基于Hibernate(十一):get和load的区别项目

1.一级缓存

1.1 概念

  hibernate默认开启一级缓存,一级缓存是放在session上的.

1.2 新建SessionTest类 

package com.hibernate.demo.test;

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

import com.hibernate.demo.bean.Employee;

public class SessionTest {

    public static void main(String[] args) {
        //加载配置文件,获取会话工厂对象
        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
        //获取会话对象
        Session session1 = sessionFactory.openSession();
        Session session2 = sessionFactory.openSession();
        
        System.out.println("log1");
        //根据id获取Employee对象
        Employee employee = (Employee) session1.get(Employee.class, 2);
        System.out.println("log2");
        Employee employee2 = (Employee) session1.get(Employee.class, 2);
        System.out.println("log3");
        Employee employee3 = (Employee) session2.get(Employee.class, 2);
        System.out.println("log4");
        
        //关闭会话对象
        session1.close();
        session2.close();
        //关闭会话工厂对象
        sessionFactory.close();
    }

}

1.3 修改Emplyee.hbm.xml文件,去除Employee与Department的many-to-one关系中的lazy="false"配置,便于查看运行结果

1.4 运行SessionTest类

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log1
Hibernate: select employee0_.emp_id as emp1_0_0_, employee0_.emp_name as emp2_0_0_, employee0_.dept_id as dept3_0_0_ from t_employee employee0_ where employee0_.emp_id=?
log2
log3
Hibernate: select employee0_.emp_id as emp1_0_0_, employee0_.emp_name as emp2_0_0_, employee0_.dept_id as dept3_0_0_ from t_employee employee0_ where employee0_.emp_id=?
log4

1.5 总结

  从1.4中打印的信息可以看出:

  (1)对于同一个Session对象session1来说,由于是第一次根据id去查询Employee对象,还没有缓存信息,所以会发送SQL语句去数据库查询,因此log1与log2之间打印出了发送的SQL信息;当第二次再根据同一个id去获取Employee对象时,由于已经有了缓存信息,所以直接从Session的缓存中获取信息,不再发送SQL去数据库查询,因此log2与log3之间没有打印出发送的SQL信息.

  (2)对于不同的Session对象session1和session2来说,缓存信息不共享,所以session2第一次根据同一个id去获取Employee对象,会发送SQL语句去数据库查询,因此log3与log4之间打印出了发送的SQL信息.

 

2.二级缓存

2.1 概念

  (1)hibernate本身不提供二级缓存,都是使用第三方二级缓存插件做支持,这里使用的是EhCache;

  (2)二级缓存是作用在SessionFactory上的;

2.2 添加ehcache的jar包,该包是net.sf.ehcache下的---容易下错包

2.3 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/keeper?characterEncoding=utf-8</property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <!-- MySQL方言配置 -->
        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
        <property name="show_sql">true</property>
        <property name="hbm2ddl.auto">update</property>
        
        <!-- 配置二级缓存 ,开启二级缓存,配置二级缓存支持类-->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        
        <!-- 配置映射文件 -->
        <mapping resource="com/hibernate/demo/bean/Employee.hbm.xml"/>
        <mapping resource="com/hibernate/demo/bean/Department.hbm.xml"/>
        <mapping resource="com/hibernate/demo/bean/Project.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

2.4 新建ehcache.xml文件,放在src目录下

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <!-- 设置存储目录 -->
    <diskStore path="java.io.tmpdir"/>
    <!-- 设置默认缓存配置 ,
    maxElementsInMemory最大缓存对象数,
    eternal是否永久存活,
    timeToIdleSeconds最大空闲秒数,
    timeToLiveSeconds最大存活秒数,
    overflowToDisk缓存对象数达到最大是否存到磁盘-->
    <defaultCache
        maxElementsInMemory="1000"
        eternal="false"
        timeToIdleSeconds="180"
        timeToLiveSeconds="180"
        overflowToDisk="true"
        />
</ehcache>

2.5 修改Employee.hbm.xml文件,添加缓存配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
<hibernate-mapping package="com.hibernate.demo.bean">
    <!-- 映射Employee类与t_employee表 -->
    <class name="Employee" table="t_employee">
        <!-- 缓存配置,只在查询的时候做缓存 -->
        <cache usage="read-only"/>
        <id name="empId" column="emp_id">
            <!-- 声明主键生成策略为自增 -->
            <generator class="native"></generator>
        </id>
        <property name="empName" column="emp_name"></property>
        <!-- 多对一,name指定多的一方中一的一方的属性名称,class指定一的一方类名,column指定多的一方表中指向一的一方表的外键字段 -->
        <many-to-one name="department" class="Department" column="dept_id"></many-to-one>
        <!-- 用于配置多对多的关系,table用于指定中间表的表名 -->
        <set name="projects" table="t_peitem">
            <!-- 中间表用于指向Employee对应表的外键列名-->
            <key column="emp_id"></key>
            <!-- 声明多对多的关系,column用于指定中间表指向Project类对应表的外键列名 ,class指定多的另一方的类名-->
            <many-to-many column="pro_id" class="Project"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

2.6 运行SessionTest类

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
log1
Hibernate: select employee0_.emp_id as emp1_0_0_, employee0_.emp_name as emp2_0_0_, employee0_.dept_id as dept3_0_0_ from t_employee employee0_ where employee0_.emp_id=?
log2
log3
log4

2.7 总结

  从2.6中打印的信息可以看出,只在session1根据id获取Employee对象时发送了SQL去数据库进行查询,session2根据同一个id获取Employee对象时,并没有发送SQL去数据库查询,可见二级缓存起作用了.

posted @ 2020-04-28 10:32  安徒生敲代码  阅读(367)  评论(0编辑  收藏  举报