为什么使用TreadLocal来实现?
具体实现如下:当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
创建com.util.HibernateUtil.java
package com.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
public HibernateUtil() {
}
private static final String RESOURCE = "resource/hibernate.cfg.xml";
private static SessionFactory sessionFactory = null;
private static ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
static {
try {
Configuration cfg = new Configuration().configure(RESOURCE);
sessionFactory = cfg.buildSessionFactory();
} catch (Exception e1) {
e1.printStackTrace();
throw new ExceptionInInitializerError("初始化hibernate错误,请检查配置文件或数据库");
}
}
public static SessionFactory getSqlSessionFactory() {
return sessionFactory;
}
public static Session getSession() {
// sessionTL的get()方法根据当前线程返回其对应的线程内部变量,
// 也就是我们需要的Session,多线程情况下共享数据库链接是不安全的。
// ThreadLocal保证了每个线程都有自己的Session。
Session session = threadLocal.get();
// 如果session为null,则打开一个新的session
if (session == null) {
session = (sessionFactory != null) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
public static void closeSession() {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
}
接下来进行测试:
首先创建com.test.MySession.java并继承Thread类
package com.test;
import org.hibernate.Session;
import com.util.HibernateUtil;
public class MySession extends Thread {
@Override
public void run() {
Session session1 = HibernateUtil.getSession();
Session session2 = HibernateUtil.getSession();
Session session3 = HibernateUtil.getSession();
// 输出session的hashCode,分辨是否是同一个session实例
System.out.println(Thread.currentThread().getName() + ":\n" +
session1.hashCode() + "\n" +
session2.hashCode() + "\n"+
session3.hashCode());
}
}
创建com.test.Test.java
package com.test;
public class SessionMain {
public static void main(String[] args) {
Thread MyThread01 = new MySession();
MyThread01.setName("线程一");
Thread MyThread02 = new MySession();
MyThread02.setName("线程二");
Thread MyThread03 = new MySession();
MyThread03.setName("线程三");
MyThread01.start();
MyThread02.start();
MyThread03.start();
}
}
运行结果:
线程一:
484059751
484059751
484059751
线程二:
839802549
839802549
839802549
线程三:
1319519604
1319519604
1319519604