Java笔记之hibernate(十二):一级缓存和二级缓存
0.说在前面
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去数据库查询,可见二级缓存起作用了.