版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/106151531
文章目录
一、缓存机制
1、缓存概述
缓存 是一种优化的方式,将数据存入到内存中,使用的时候会直接从这块内存中获取,不用通过存储源,这块内存我们把它称之为 缓存。
在 Hibernate 中提供了很多种优化手段,比如缓存机制、抓取策略等。他们的目的只有一个,就是尽可能的提高性能。本章主要讲解 Hibernate 中的第一个优化手段 —— 缓存机制。
2、Hibernate 中的缓存(一级缓存)
在 Hibernate 中提供了两种缓存机制:一级缓存 和 二级缓存。
一级缓存 是 Session 级别的缓存,它的生命周期与 Session 一致(一级缓存 是由 Session 中一系列的 Java 集合构成的)。它是 Hibernate 自带的,不可以弃用。
而 Hibernate 的 二级缓存 是 SessionFactory 级别的缓存,它必须手动开启才能使用,一般项目中很少使用,一般都用 Redis 来代替,大家了解一下有这么个东西就可以了。
1)特点
当应用程序调用 Session 接口的
save()
、update()
、saveOrUpdate()
方法时,如果 Session 缓存(一级缓存)中没有相应的对象,Hibernate 就会自动的把从数据库中查询到的对象信息加入到 一级缓存 中去。当调用 Session 接口的
load()
、get()
方法,以及 Query 接口中的list()
、iterator()
方法时,会判断缓存中是否存在该对象,有则返回,不会查询数据库;如果缓存中没有要查询的对象,再去数据库中查询对应的对象,并添加到 一级缓存 中。当调用 Session 的
close()
方法时,Session 缓存(一级缓存)会被清空。
@Test
// 证明一级缓存的存在
public void demo3() {
Session session = HibernateUtils.openSession(); // HibernateUtils是自己封装的工具类,从中获取 Session 对象
Transaction tx = session.beginTransaction();
// Customer c = session.get(Customer.class, 1); // 第一次会从数据库中取,会发送SQL语句
// System.out.println(c);
// Customer c2 = session.get(Customer.class, 1); // 缓存中存在,会直接从缓存中取,不会发送SQL语句
// System.out.println(c2);
Customer c = new Customer();
c.setCust_name("张三");
Serializable id = session.save(c); // 插入到数据库中,并插入到缓存中
Customer c2 = session.get(Customer.class, id); // 会直接从缓存中取
System.out.println(c2);
tx.commit();
session.close();
}
2)清空
@Test
// 一级缓存的清空
public void demo4() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer c1 = session.get(Customer.class, 1); // 发送SQL语句,将数据放到缓存中(持久化对象)
System.out.println(c1);
// 清空Session缓存中的数据
// session.clear(); // 清空全部数据
session.evict(c1); // 清空指定对象
Customer c2 = session.get(Customer.class, 1); // 发送SQL语句,将数据放到缓存中(持久化对象)
System.out.println(c2);
tx.commit();
session.close();
}
二、事务管理
关于 事务 这一块,我之前写过一篇关于 事务 的博客,自我感觉写的还算通俗易懂,大家可以参考参考:事务博客
1、配置事务隔离级别
在
hibernate.cfg.xml
中进行 配置事务隔离级别,如下:
<!-- 设置事务隔离级别
1 -- Read uncommitted isolation(读未提交)
2 -- Read committed isolation(读已提交)
4 -- Repeatable read isolation(可重复读)
8 -- Serializable isolation(序列化)
-->
<property name="hibernate.connection.isolation">4</property>
2、Service 层的事务
我们如果要在 Service 层进行事务管理,就必须要保证连接对象是同一个。对于实现同一个连接对象有两个办法:
向下传递
在外面获得一个连接,直接传入 Dao 层,在 Dao 层中直接使用外面传来的这个连接对象就可以了,DBUtils 这个小工具就是采用了这个办法。
使用 ThreadLocal 对象
这个对象是绑定线程的对象,将连接对象绑定到当前线程中,然后在 Dao 层的方法中,直接通过当前线程来获得这个连接对象即可。
Hibernate 框架采用了第二个办法,它的内部已经绑定好了 ThreadLocal 对象,在 SessionFactory 中提供了一个方法getCurrentSession()
,通过这个方法能获得当前线程中的 Session,但是这个方法默认是不能使用的,需要通过配置才能开启使用。Hibernate 解决 Service 层事务管理的步骤如下:
1)配置 Session 管理方式
在 Hibernate 的配置文件中,我们可以使用
hibernate.current_session_context_class
属性来设置 Session 管理方式,它的可选值有:
thread
:Session 对象的生命周期与本地线程绑定;jta
:Session 对象的生命周期与 JTA 事务绑定;managed
:Hibernate 委托当前程序来管理 Session 对象的生命周期。
在
hibernate.cfg.xml
中进行如下配置:
<!-- 配置当前线程绑定的 Session -->
<property name="hibernate.current_session_context_class">thread</property>
2)测试
注意:在使用
getCurrentSession()
方法是不能关闭 Session 对象的,因为在线程结束后会自动关闭 Session 对象,如果手动关闭就会报错!
@Test
public void demo1() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer c = session.get(Customer.class, 1);
System.out.println(c);
tx.commit();
}
3)封装 HibernateUtils 工具类
/**
* Hibernate的工具类
* @author Administrator
*
*/
public class HibernateUtils {
private static Configuration cfg = null;
private static SessionFactory sf = null;
static {
cfg = new Configuration().configure();
sf = cfg.buildSessionFactory();
}
public static Session openSession() {
return sf.openSession();
}
public static Session getCurrentSession() {
return sf.getCurrentSession();
}
}