zoukankan      html  css  js  c++  java
  • hibernate中的ThreadLocalSessionContext和Transaction的关系

           最近在做一个铁科院的医保项目框架是SSH,这种经典框架相信很多人对这个都很熟悉,不过对有些概念性的东西不知道你是否清楚,例如我们都知道hibernate通过session来操作数据库完成CRUD操作,Spring在同hibernate集成的时候可以将hibernate的sessionfactory拿过来管理,为了更方便操作数据库spring封装了一个getHibernateTemplate类,该类也可以完成CRUD操作,在使用灵活行方面比hibernate灵活了一些,操作也简便。

           对数据库的操作都需要控制事务保证操作原子性,session在操作数据库的时候事务是怎么控制的呢,我们只知道事务是随着session一起开启和关闭的,具体来看一下是如何实现。

           通过写底层的一些方法,了解了getCurrentSession()与openSession()的区别,前者是从当前线程中获取session,使用完后不需要自己关闭;后者是打开一个新的session,需要自己手动开发和关闭;

           我们操作的是session,它和事务有什么关系呢?换句话说,session和事务生命周期是否相同?分别何时开启?何时关闭?

           想要清楚这两者的关系,先要了解session机制,session是hibernate框架中一个操作ORM映射关系的接口,该接口有三种类型,分别为ThreadLocalSessionContext、JTASessionContext、ManagedSessionContext,这三个实现类实现了CurrentSessionContext接口。

           getCurrentSession()这个方法得到的就是CurrentSessionContext接口,提供的默认实现类为ThreadLocalSessionContext

    <span style="font-size:14px;">SessionFactory类
    public abstract interface SessionFactory extends Referenceable, Serializable
    {
      public abstract Session openSession(Connection paramConnection);
    
      public abstract Session getCurrentSession()
    throws HibernateException;
    }
    SessionFactory实现类
    public final class SessionFactoryImpl
      implements SessionFactory, SessionFactoryImplementor
    {
    
     private final transient CurrentSessionContext currentSessionContext;
    
     public Session getCurrentSession()
        throws HibernateException
      {
        if (this.currentSessionContext == null) {
          throw new HibernateException("No CurrentSessionContext configured!");
        }
        return this.currentSessionContext.currentSession();
      }
    }
    CurrentSessionContext接口里面只有一个方法,currentSession()
    public abstract interface CurrentSessionContext extends Serializable
    {
      public abstract Session currentSession()
        throws HibernateException;
    }
    public class ThreadLocalSessionContext
      implements CurrentSessionContext
    {  
       private static final ThreadLocal context = new ThreadLocal();
       
       public final org.hibernate.classic.Session currentSession()
        throws HibernateException
      {
        org.hibernate.classic.Session current = existingSession(this.factory);
        if (current == null) {
          current = buildOrObtainSession();
    
          current.getTransaction().registerSynchronization(buildCleanupSynch());
    
          if (needsWrapping(current)) {
            current = wrap(current);
          }
    
          doBind(current, this.factory);
        }
        return current;
      }
    
    
    }
    </span>

           Session与Transaction进行关联是在底层session实现时操作的,你是否记得代理模式的作用,代理对象可以在客户端和目标对象之间起到中介的作用,可以增加一些额外,这样起到了保护目标对象的作用,在这里事务正式通过代理模式给session添加事务的

    如果只从ThreadLocalSessionContext的名称上看,它所做的就是把一个session绑定到当前线程上,让当前线程作为session的上下文。这样,在service里不同的dao通过sessionFactory.getCurrentSession()得到的将是当前线程上的同一个session,这是非常必要的做法,通过使用同一个session确保了持久化对象的一致性。但是从ThreadLocalSessionContext的代码来看,它并只是做了这一件事,它还做了另外一件非常“醒目”的事情:即给session包裹了一层代理org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper,这个代理将拦截session的操作,对session的使用做出了如下的限制:


    1.在没有显式地开始一个事务之前,不能使用session的任何数据访问方法。

    2.一旦事务提交,session将自动close。


           通过上面这样的限制就使得事务同session的周期变的一致了,由于session放在了一个ThreadLocal里面,如此以来,threadlocal、session、transaction三者的生命周期是一致的,达到了对于同一个请求在同一个线程同一个事务中,session也是同一个session,既保证了持久化对象的一致性,又保证了事务的机制。

     

            相反在提交事务之后,如果再从threadlocal中取得session将是一个新的session对象。因此,session的周期和事务是绑定在一起的。

           ThreadLocal在这里当做上下文来存放session对象,每次在用的时候只需要从这里面取出来就可以了。


  • 相关阅读:
    Docker Swarm
    服务器虚拟化
    kubernets的工作流程
    配置docker阿里云加速器
    kubeadm 安装kubernetes集群。
    linux的10个最危险的命令
    18个网络带宽常用命令
    column命令
    dd命令
    scp命令
  • 原文地址:https://www.cnblogs.com/lilongsheng1125/p/4978511.html
Copyright © 2011-2022 走看看