hibernate—OpenSesssion和getCurrentSession及单例和多例模式的理解总结

之所以会有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()。

点赞