\首先,我们先来看一段代码,传统的Hibernate获得Session进行CRUD的操作:
// 1.创建Configuration引用
Configuration configuration = new Configuration();
// 2.创建SessionFactory,SessionFactory是一个重量级对象,所谓重量级对象会很吃计算机的内存,因为该对象要完成对映射文件的管理,
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.获得Session
Session session = sessionFactory.openSession();
Transaction ts = session.beginTransaction();
/*
* 此处省略CRUD操作代码
*/
// 4.事务提交
ts.commit();
// 5.关闭连接
session.close();
正如代码中说的,SessionFactory是一个吃内存的对象,一个项目如果针对一个数据库最好将SessionFactory对象做成单例模式即可.像以上的代码不仅冗余的代码很多,而且使用起来每次打开一个新的Session对于多个页面之间的事务处理是十分不方便的,比如说你的WEB项目有两个控制器(controller),分别命名为A和B,在A页面进行进行转账业务,在B页面进行获取账户余额,这两个应该是放在一个事务里面处理,但是由于A页面和B页面都需要进行openSession()而这个方法返回的Session不是同一个(打印HashCode())对象,所以不方便进行多个页面的事务处理,现在我们就有这样的一个需求,多个页面使用一个Session对象,这个需求要怎么实现那?
我们可以把Session放在一个线程局部变量中(ThreadLocal),在同一个执行路径里面这个变量可以一直被调用,而且获得的都是同一个变量
ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();//通过泛型指定存储的是什么类型的变量
threadLocal.set(Session session);//设置Session
Session session = threadLocal.get();//获得Session
下面开始HibernateUtil的封装:
package com.wsl.util;
import org.hibernate.*;
import org.hibernate.cfg.*;
/**
*
* @author 小吴同学
*
*/
public class HibernateUtil {
// SessionFactory会话工厂
private static SessionFactory sessionFactory = null;
// 线程局部变量管理
private static ThreadLocal
threadLocal = new ThreadLocal
();
// 写在static块是因为该块只会被类被ClassLoader加载到虚拟机的时候执行一次
static {
try {
// 使用Configuration()对象.configure()方法去读取src/hibernate.cfg.xml配置文件
sessionFactory = new Configuration().configure()
.buildSessionFactory();// 产生一个SessionFactory
} catch (Throwable e) {// 如果在执行static块的时候出现任何的Throwable(Error和Exception的类的父类)则处理
// 抛出明确的static程式错误的异常
throw new ExceptionInInitializerError(e);
}
}
/**
*
* 获得SessionFactory这个就不说了
*
* @return SessionFactory
*/
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* 获得Session会话对象
*
* @return Session
*/
public static Session getSession() {
// 首先从线程局部变量中有没有session,以免还要openSession();
Session session = threadLocal.get();
// 如果是空或者没有打开
if (session == null || !session.isOpen()) {
// 则打开(因为static块有可能出错,所以这里进行三元判断)
session = sessionFactory != null ? sessionFactory.openSession()
: null;
// 设置到线程局部变量中
threadLocal.set(session);
}
return session;
}
// 关闭Session
public static void closeSession() {
// 获得线程局部变量中的session
Session session = threadLocal.get();
// 设置为空,当再次调用openSession()的时候才能打开Session
threadLocal.set(null);
if (session != null) {
session.close();
}
}
}