【Hibernate笔记整理七】缓存机制与事务管理

版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址: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 层进行事务管理,就必须要保证连接对象是同一个。对于实现同一个连接对象有两个办法:

  1. 向下传递

    在外面获得一个连接,直接传入 Dao 层,在 Dao 层中直接使用外面传来的这个连接对象就可以了,DBUtils 这个小工具就是采用了这个办法。

  2. 使用 ThreadLocal 对象

    这个对象是绑定线程的对象,将连接对象绑定到当前线程中,然后在 Dao 层的方法中,直接通过当前线程来获得这个连接对象即可。
     
    Hibernate 框架采用了第二个办法,它的内部已经绑定好了 ThreadLocal 对象,在 SessionFactory 中提供了一个方法 getCurrentSession(),通过这个方法能获得当前线程中的 Session,但是这个方法默认是不能使用的,需要通过配置才能开启使用。

Hibernate 解决 Service 层事务管理的步骤如下:

1)配置 Session 管理方式

Hibernate 的配置文件中,我们可以使用 hibernate.current_session_context_class 属性来设置 Session 管理方式,它的可选值有:

  • thread:Session 对象的生命周期与本地线程绑定;
  • jta:Session 对象的生命周期与 JTA 事务绑定;
  • managedHibernate 委托当前程序来管理 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();
	}
	
}


博客中若有不恰当的地方,请您一定要告诉我。前路崎岖,望我们可以互相帮助,并肩前行!



猜你喜欢

转载自blog.csdn.net/sun8112133/article/details/106151531