目录
前言
Hibernate版本4.3,为了避免频繁地去创建配置类对象、会话工厂和会话对象等操作,和重复的代码过多的现象,将这个获取会话对象和关闭会话对象等的操作抽象出来构建一个工具类。对外提供静态方法,方便调用。据说都不常用了,估计这辈子就写这一次也说不一定哈哈。
正文
工具类完整代码
package utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
/**
* hibernate的工具类
* @author 傻孩子
*
*/
public class HibernateUtil {
private static StandardServiceRegistry ssr;
private static SessionFactory sf;
private static ThreadLocal<Session> localThread = new ThreadLocal<Session>();
static{
Configuration config = new Configuration().configure();
ssr = new StandardServiceRegistryBuilder().applySettings(config.getProperties())
.build();
sf = config.buildSessionFactory(ssr);
}
/**
* 获取会话
* @return
*/
public static Session getSession(){
Session session = localThread.get();
if(session == null || !session.isOpen()){
session = sf.openSession();
localThread.set(session);
}
return session;
}
/**
* 关闭会话、会话工厂和会话注册
*/
public static void close(){
Session session = localThread.get();
if(session != null){
session.close();
localThread.remove();
sf.close();
StandardServiceRegistryBuilder.destroy(ssr);
}
}
}
工具类代码解释
1、ssr和ssf
private static StandardServiceRegistry ssr;
private static SessionFactory sf;
private static ThreadLocal<Session> localThread = new ThreadLocal<Session>();
static{
Configuration config = new Configuration().configure();
ssr = new StandardServiceRegistryBuilder().applySettings(config.getProperties())
.build();
sf = config.buildSessionFactory(ssr);
}
当前版本, 要获取到Hibernate的Session对象,需要通过StandardServiceRegistryBuilder对象的方法applySettings(config.getProperties())设置StandardServiceRegistryBuilder的对象,然后调用方法build()获取到StandardServiceRegistry 对象,再通过config.buildSessionFactory(ssr)获取SessionFactory对象,通过这个对象的方法openSession()才能开启会话获取到Session对象。
看不懂?我也看不懂,就是人家设计的类,要这么使用嘛。
因为这一系列步骤,在后面的获取会话静态方法和关闭资源的静态方法中都会使用到,因此将这一个过程在静态代码块中执行,并将ssr和sf写在代码块和后面的静态方法之外,好全局调用。
Session是线程不安全的,并发时获取的Session不是同一个,为了统一管理使用了ThreadLocal<Session>,使一个线程只有一个session。写在外头,也是因为后面两个方法都要使用,设计为局部变量不恰当。
2、获取Session静态方法
/**
* 获取会话
* @return
*/
public static Session getSession(){
Session session = localThread.get();
if(session == null || !session.isOpen()){
session = sf.openSession();
localThread.set(session);
}
return session;
}
先从threadLocal的方法get()获取对象,看是否有Session会话,有则会得到一个Session对象没有就是null。
若获取的对象是否为null或者是关闭状态,就需要新建或者打开一个session对象,存储在threadLocal中,并返回session给调用者。
3、关闭资源
/**
* 关闭会话、会话工厂和会话注册
*/
public static void close(){
Session session = localThread.get();
if(session != null){
session.close();
localThread.remove();
sf.close();
//销毁StandardserviceRegistry实例
StandardServiceRegistryBuilder.destroy(ssr);
}
}
同获取会话方法一样,需要先从管理session的threadLocal中先获取对象,如果有就调用方法close关闭,并调用threadLocal方法remove()移除session对象。
而后因为hibernate4.x在创建sessionFactory时,会自动创建一个线程,由该线程负责创建和管理sessionFactory,所以需要关闭sessionFactory,即“sf.close();”,目的是为了关闭该线程。
总结
1、理解静态变量和静态代码块设计的理由
2、理解如何使用ThreadLocal集合
完