之所以会有OpenSesssion() 和getCurrentSession()的区别,是因为session不是线程安全的,特别是多线程并发的时候更会导致数据混乱。
这一点可以这样解释,OpenSesssion()打开线程操作。操作完成之后,关闭线程。也清除了数据,如果不关闭线程。则数据还没有清除,继续留在对象上面,后面的线程进行的数据操作必然与原来的残留的数据混乱,所以OpenSesssion()必须关闭线程。
可是即使关闭了线程,还有安全问题,那就是在单线程操作未结束的时候突然有一个线程开始涌进来,也就是俗话说的多线程并发的情况。可是这个时候多线程的数据又混乱了。
就好比读者君不小心在地上撒了一万块钱,作者君心思灵动,立马拿出来一千块钱也撒过去,然后咱们一块捡钱,你说同样的时间下,我能捡多少钱。就算长期码代码导致腿脚不灵活,想来三四千可以有吧,这也算赚的啊。
这就是opensession为何必须关闭以及session线程不安全的原因。也是getCurrentSession()出现的原因。
毕竟他是单例模式。所以为了解决数据混乱问题,采用多例模式解决并发问题。
而sessionFactory是线程安全的。多个并发的线程可以同时访问一个sessionFactory并从中获取session实例,这也是为何封装的时候不会讲这两者封装到一块的原因。
那么什么是单例模式与多例模式呢,其实可以这样理解,单例模式就是原件使用模式,多例模式就是复印件使用模式。
如果原件使用,稍有损坏,就不能用了,但是用复印件使用,即使丢了,烧了,也无损继续使用,不过是通过原件再复印一分而已。
那么具体到hibernate的session管理上就是threadLoacl模式解决方案。
private static SessionFactory sessionFactory = null;
//声明一个session类型的线程局部变量。
private static final ThreadLocal<Session> tl = new ThreadLocal<Session>();
//static代码块,安全的线程,每一次运行都必须加载。
static {
// 读取并解析配置文件,以及映射文件
try {
Configuration configuration = new Configuration().configure();
// 测试
System.out.println("成功");
// 创建SessionFactory实例
sessionFactory = configuration.buildSessionFactory();
} catch (HibernateException e) {
e.printStackTrace();
}
}
public static Session getSession() {
//先获得一个session
Session session = tl.get();
//没有现成的,就临时创建一个新的使用。
if (session == null) {
if (sessionFactory!=null) {
//建一个新的session
session = sessionFactory.openSession();
tl.set(session);
}
}
//有现成的直接拿来用。
return session;
}
所以getCurrentSession()不必手动关闭session。会在提交或者回滚之后自动关闭。
那么总结如下: OpenSesssion()不绑定线程,线程不安全,需手动关闭session。 getCurrentSession()绑定当前线程,线程安全,事务提交或者回滚之后自动关闭session。所以现如今,安全第一的情况下基本上淘汰了OpenSesssion()。推荐使用 getCurrentSession()。