Hibernate的二级缓存

本文详细介绍了Hibernate二级缓存的概念、配置及使用方法,并通过示例演示了如何配置二级缓存,以及不同缓存策略的应用场景。
Hibernate二级缓存:
二级缓存也称位进程级缓存或者sessionFactory级缓存,二级缓存可以被所有的session共享

二级缓存的配置和使用:
*将echcache.xml(这个文件在hibernate代码包中的etc 目录下)拷贝到src目录下
*开启二级缓存 修改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 usage=""> 标签
* 在hibernate.cfg.xml中配置
<class-cache class="com.june.hibernate.Student" usage="read-only"/>
我推荐优先使用<read-only>
1. <read-only>
如果你的应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读 缓存。这是最简单,也是实用性最好的方法。
甚至在集群中,它也能完美地运作。
2. read/write
如果应用程序需要更新数据,那么使用读/写缓存 比较合适。 如果应用程序要求“序列化事务”的隔离级别(serializable transaction
isolation level), 那么就决不能使用这种缓存策略。如果在JTA环境中使用缓存,你必须指定hibernate.transaction.manager_lookup_
class属性的值, 通过它,Hibernate才能知道该应用程序中JTA的TransactionManager的具体策略。 在其它环境中,你必须保证在Session.close()
、或Session.disconnect()调用前, 整个事务已经结束。 如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate
内置的缓存策略并不支持锁定功能
3. nonstrict read/write
如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离, 那么比较适合使用非严格读/写
缓存策略。如果在JTA环境中使用该策略, 你必须为其指定hibernate.transaction.manager_lookup_class属性的值, 在其它环境中,你必须保证在
Session.close()、或Session.disconnect()调用前, 整个事务已经结束


二级缓存的是缓存实体对象的:
了解一级缓存的交互(session.setCacheMode())
主要是 CacheMode.NORMAL
CacheMode.PUT
CacheMode.GET
具体常见HibernateReference
有如下2个类 :

public class Clazz {
private Integer id;
private String name;
private Set<Student> students=new HashSet<Student>();
}
public class Student {
private Integer id;
private String name;
private Clazz clazz;
}


映射文件为(我们对students类设置缓存):

<class name="com.june.hibernate.Clazz" table="t_clazz">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="students" inverse="true">
<key column="clazz"/>
<one-to-many class="com.june.hibernate.Student"/>
</set>
</class>
<class name="com.june.hibernate.Student" table="t_student">
<!--
<cache usage="read-only"/>-->
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<many-to-one name="clazz" cascade="save-update"></many-to-one>
</class>

Hibernate 配置文件:

<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_cache_level_2</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<!-- 开启二级缓存 hibernate默认就是开启的 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 指定缓存产品提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<mapping resource="com/june/hibernate/Clazz.hbm.xml"/>
<mapping resource="com/june/hibernate/Student.hbm.xml"/>
<!-- 我推荐在此设置二级缓存 而不是在具体的类配置文件中设置 因为在此设置会对非常清楚的了解 那些是设了二级缓存的 那些是没有设的-->
<class-cache class="com.june.hibernate.Student" usage="read-only"/>
</session-factory>
</hibernate-configuration>


测试用例:

package com.june.hibernate;

import junit.framework.TestCase;

import org.hibernate.CacheMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

public class CacheLevel2Test extends TestCase{
/**
* 开启2个session分别调用load
*/
public void testLoad(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}

try{
//第二个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
//不会发出session 因为开启了二级缓存 session共享二级缓存
// load()方法也使用二级缓存
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
/**
* 开启2个session分别调用get()
*/
public void testGet(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.get(Student.class,1);
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}

try{
//第二个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.get(Student.class,1);
//也不会发出session 因为开启了二级缓存 session共享二级缓存
//get()也使用二级缓存
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
/**
* 开启2个session分别调用load 用sessionFactory 清除二级缓存
*/
public void testLoad2(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
SessionFactory factory=HibernateUtil.getSessionFactory();
//管理二级缓存
//factory.evict(Student.class,1);
factory.evict(Student.class);
try{
//第二个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
//会发出查询sql 主要是由于二级缓存中的数据被清楚啦
System.out.println("student1.name="+student1.getName());

tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
/**
* 一级缓存和二级缓存的交互
* 默认为CacheMode.NORMAL
* 即以及缓存即向二级缓存中写数据也从二级缓存中读数据
*/
public void testCache(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
try{
//第2个session
session=HibernateUtil.getSession();
//仅从二级缓存读数据 而不从二级缓存写数据
session.setCacheMode(CacheMode.GET);
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
//不会发出sql 语句
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
SessionFactory factory=HibernateUtil.getSessionFactory();

try{
//第3个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
// 因为session设置了CacheMode位GET 所以二级缓存中没有数据
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
public void testCache2(){
Session session=null;
Transaction tx=null;
try{
//第一个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
try{
//第2个session
session=HibernateUtil.getSession();
//仅从二级缓写读数据 而不从二级缓读写数据
session.setCacheMode(CacheMode.PUT);
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
SessionFactory factory=HibernateUtil.getSessionFactory();

try{
//第3个session
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Student student1=(Student)session.load(Student.class,1);
// 因为session设置了CacheMode位GET 所以二级缓存中没有数据
System.out.println("student1.name="+student1.getName());
tx.commit();
}catch(Exception e){
e.printStackTrace();
tx.rollback();
}finally{
HibernateUtil.colseSession(session);
}
}
}



---------------------------------------------------------------------
在运新单元测试之前请初始化数据 初始化数据类 请参照前一篇文章的的 InitialData类
运行了以上的单元测试 我们可以对hibernate的二级缓存 就会有个比较清晰的认识
采用PyQt5框架与Python编程语言构建图书信息管理平台 本项目基于Python编程环境,结合PyQt5图形界面开发库,设计实现了一套完整的图书信息管理解决方案。该系统主要面向图书馆、书店等机构的日常运营需求,通过模块化设计实现了图书信息的标准化管理流程。 系统架构采用典型的三层设计模式,包含数据存储层、业务逻辑层和用户界面层。数据持久化方案支持SQLite轻量级数据库与MySQL企业级数据库的双重配置选项,通过统一的数据库操作接口实现数据存取隔离。在数据建模方面,设计了包含图书基本信息、读者档案、借阅记录等核心数据实体,各实体间通过主外键约束建立关联关系。 核心功能模块包含六大子系统: 1. 图书编目管理:支持国际标准书号、中国图书馆分类法等专业元数据的规范化著录,提供批量导入与单条录入两种数据采集方式 2. 库存动态监控:实时追踪在架数量、借出状态、预约队列等流通指标,设置库存预警阈值自动提醒补货 3. 读者服务管理:建立完整的读者信用评价体系,记录借阅历史与违规行为,实施差异化借阅权限管理 4. 流通业务处理:涵盖借书登记、归还处理、续借申请、逾期计算等标准业务流程,支持射频识别技术设备集成 5. 统计报表生成:按日/月/年周期自动生成流通统计、热门图书排行、读者活跃度等多维度分析图表 6. 系统维护配置:提供用户权限分级管理、数据备份恢复、操作日志审计等管理功能 在技术实现层面,界面设计遵循Material Design设计规范,采用QSS样式表实现视觉定制化。通过信号槽机制实现前后端数据双向绑定,运用多线程处理技术保障界面响应流畅度。数据验证机制包含前端格式校验与后端业务规则双重保障,关键操作均设有二次确认流程。 该系统适用于中小型图书管理场景,通过可扩展的插件架构支持功能模块的灵活组合。开发过程中特别注重代码的可维护性,采用面向对象编程范式实现高内聚低耦合的组件设计,为后续功能迭代奠定技术基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值