hibernate二级缓存
二级缓存也称进程级的缓存或SessionFactory级的缓存,二级缓存可以被所有的session共享
二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存
二级缓存的配置和使用:
* 将echcache.xml文件拷贝到src下:
二级缓存也称进程级的缓存或SessionFactory级的缓存,二级缓存可以被所有的session共享
二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存
二级缓存的配置和使用:
* 将echcache.xml文件拷贝到src下:
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
* 开启二级缓存,修改hibernate.cfg.xml文件
<property name="hibernate.cache.use_second_level_cache">true</property>
* 指定缓存产品提供商,修改hibernate.cfg.xml文件
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
* 指定那些实体类使用二级缓存(两种方法)
* 在映射文件中采用<cache>标签:<cache usage="read-only"/>
* 在hibernate.cfg.xml文件中,采用<class-cache>标签:<class-cache class="com.bjsxt.hibernate.Student" usage="read-only"/>
二级缓存是缓存实体对象的
了解一级缓存和二级缓存的交互
invalidation n. 失效;无效
replication n. 复制;回答;反响
package com.bjsxt.hibernate;
import java.io.Serializable;
import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import junit.framework.TestCase;
public class CacheLevel2Test extends TestCase {
/**
* 开启两个session,分别调用load
* 测试结果:select ... ...
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql,因为开启了二级缓存,session是共享二级缓存的
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启两个session,分别调用get
* 测试结果:select ... ...
*/
public void testCache2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql,因为开启了二级缓存,session是共享二级缓存的
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启两个session,分别调用load,再使用SessionFactory清除二级缓存
* 测试结果:select ... select ...
*/
public void testCache3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//管理二级缓存
SessionFactory factory = HibernateUtils.getSessionFactory();
//factory.evict(Student.class);//清除所有对象
factory.evict(Student.class, 1);//清除某一个对象
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//会发出查询sql,因为二级缓存中的数据被清除了
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 一级缓存和二级缓存的交互
* 1、执行load默认会把数据写入二级缓存一份,并且能读出来。
* 2、设置CacheMode_GET,则只能把数据从二级缓存中读出来,不能写进去一份,此时二级缓存中是没有数据的(二级缓存中没有数据,能读出来)
* 3、设置CacheMode_PUT,则只能把数据写入二级缓存中一份,此时二级缓存中是有一份数据的,但是却不能把数据从二级缓存中读出来(二级缓存中有数据,读不出来)
*/
//Test1:先load默认,再load默认
//测试结果:select ... ...
public void testCache4_A_defaultLoad_defaultLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//向一级缓存和二级缓存中各写入一份
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开一session,清理一级缓存的数据,但是二级缓存中还有数据,再加载的时候直接用二级缓存中的数据
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
//Test2:先设置load的模式为:CacheMode.GET,再load默认
//测试结果:select ... select ...
public void testCache4_B_CacheModeGET_defaultLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//仅从二级缓存读数据,而不向二级缓存写数据
session.setCacheMode(CacheMode.GET);
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开的session,所以一级缓存中是没有数据的
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//此时二级缓存中是没有数据的,要读出数据,得先发select查
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
//Test3:先设置load的模式为:CacheMode.GET,再load默认,再load默认
//测试结果:select ... select ... ...
public void testCache4_C_CacheModeGET_defaultLoad__defaultLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//仅从二级缓存读数据,而不向二级缓存写数据
session.setCacheMode(CacheMode.GET);
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开的session,所以一级缓存中是没有数据的
//下面的第二个session中,二级缓存中被写入数据
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//此时二级缓存中是没有数据的,要读出数据,得先发select查
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开每三个session
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不发sql,因为第二个session中,二级缓存中被写入数据,所以在第三个session中直接使用
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
//Test4:先设置load的模式为:load=CacheMode.GET,再load默认,再load=CacheMode.PUT
//测试结果:select ... select ... select ...
public void testCache4_D_CacheModeGET_defaultLoad_CacheModePUT() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//仅从二级缓存读数据,而不向二级缓存写数据
session.setCacheMode(CacheMode.GET);
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//发出sql语句,因为session设置了CacheMode为GET,所以二级缓存中没有数据
//此时二级缓存中是没有数据的,要读出数据,得先发select查
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//只向二级缓存写数据,而不从二级缓存读数据
session.setCacheMode(CacheMode.PUT);
//会发出查询sql,因为session将CacheMode设置成了PUT
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/* 20:38:10,265 WARN CacheFactory:43 - read-only cache configured for mutable class: com.bjsxt.hibernate.Student
20:38:10,265 WARN EhCacheProvider:86 - Could not find configuration [com.bjsxt.hibernate.Student]; using defaults.
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.classesid as classesid1_0_ from t_student student0_ where student0_.id=?
student.name=班级0的学生0
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.classesid as classesid1_0_ from t_student student0_ where student0_.id=?
student.name=班级0的学生0
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.classesid as classesid1_0_ from t_student student0_ where student0_.id=?
student.name=班级0的学生0*/
}
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
* 开启二级缓存,修改hibernate.cfg.xml文件
<property name="hibernate.cache.use_second_level_cache">true</property>
* 指定缓存产品提供商,修改hibernate.cfg.xml文件
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
* 指定那些实体类使用二级缓存(两种方法)
* 在映射文件中采用<cache>标签:<cache usage="read-only"/>
* 在hibernate.cfg.xml文件中,采用<class-cache>标签:<class-cache class="com.bjsxt.hibernate.Student" usage="read-only"/>
二级缓存是缓存实体对象的
了解一级缓存和二级缓存的交互
invalidation n. 失效;无效
replication n. 复制;回答;反响
package com.bjsxt.hibernate;
import java.io.Serializable;
import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import junit.framework.TestCase;
public class CacheLevel2Test extends TestCase {
/**
* 开启两个session,分别调用load
* 测试结果:select ... ...
*/
public void testCache1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql,因为开启了二级缓存,session是共享二级缓存的
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启两个session,分别调用get
* 测试结果:select ... ...
*/
public void testCache2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql,因为开启了二级缓存,session是共享二级缓存的
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 开启两个session,分别调用load,再使用SessionFactory清除二级缓存
* 测试结果:select ... select ...
*/
public void testCache3() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//管理二级缓存
SessionFactory factory = HibernateUtils.getSessionFactory();
//factory.evict(Student.class);//清除所有对象
factory.evict(Student.class, 1);//清除某一个对象
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//会发出查询sql,因为二级缓存中的数据被清除了
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/**
* 一级缓存和二级缓存的交互
* 1、执行load默认会把数据写入二级缓存一份,并且能读出来。
* 2、设置CacheMode_GET,则只能把数据从二级缓存中读出来,不能写进去一份,此时二级缓存中是没有数据的(二级缓存中没有数据,能读出来)
* 3、设置CacheMode_PUT,则只能把数据写入二级缓存中一份,此时二级缓存中是有一份数据的,但是却不能把数据从二级缓存中读出来(二级缓存中有数据,读不出来)
*/
//Test1:先load默认,再load默认
//测试结果:select ... ...
public void testCache4_A_defaultLoad_defaultLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//向一级缓存和二级缓存中各写入一份
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开一session,清理一级缓存的数据,但是二级缓存中还有数据,再加载的时候直接用二级缓存中的数据
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
//Test2:先设置load的模式为:CacheMode.GET,再load默认
//测试结果:select ... select ...
public void testCache4_B_CacheModeGET_defaultLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//仅从二级缓存读数据,而不向二级缓存写数据
session.setCacheMode(CacheMode.GET);
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开的session,所以一级缓存中是没有数据的
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//此时二级缓存中是没有数据的,要读出数据,得先发select查
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
//Test3:先设置load的模式为:CacheMode.GET,再load默认,再load默认
//测试结果:select ... select ... ...
public void testCache4_C_CacheModeGET_defaultLoad__defaultLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//仅从二级缓存读数据,而不向二级缓存写数据
session.setCacheMode(CacheMode.GET);
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开的session,所以一级缓存中是没有数据的
//下面的第二个session中,二级缓存中被写入数据
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//此时二级缓存中是没有数据的,要读出数据,得先发select查
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//新开每三个session
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//不发sql,因为第二个session中,二级缓存中被写入数据,所以在第三个session中直接使用
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
//Test4:先设置load的模式为:load=CacheMode.GET,再load默认,再load=CacheMode.PUT
//测试结果:select ... select ... select ...
public void testCache4_D_CacheModeGET_defaultLoad_CacheModePUT() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//仅从二级缓存读数据,而不向二级缓存写数据
session.setCacheMode(CacheMode.GET);
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//发出sql语句,因为session设置了CacheMode为GET,所以二级缓存中没有数据
//此时二级缓存中是没有数据的,要读出数据,得先发select查
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
try {
session = HibernateUtils.getSession();
session.beginTransaction();
//只向二级缓存写数据,而不从二级缓存读数据
session.setCacheMode(CacheMode.PUT);
//会发出查询sql,因为session将CacheMode设置成了PUT
Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
/* 20:38:10,265 WARN CacheFactory:43 - read-only cache configured for mutable class: com.bjsxt.hibernate.Student
20:38:10,265 WARN EhCacheProvider:86 - Could not find configuration [com.bjsxt.hibernate.Student]; using defaults.
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.classesid as classesid1_0_ from t_student student0_ where student0_.id=?
student.name=班级0的学生0
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.classesid as classesid1_0_ from t_student student0_ where student0_.id=?
student.name=班级0的学生0
Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.classesid as classesid1_0_ from t_student student0_ where student0_.id=?
student.name=班级0的学生0*/
}