MyBatis sqlSession

转自:http://blog.csdn.net/asdfsadfasdfsa/article/details/52037325

工作中,需要学习一下MyBatis sqlSession的产生过程,翻看了mybatis-spring的源码,阅读了一些mybatis的相关doc,对mybatis sqlSession有了一些认知和理解,这里简单的总结和整理一下。

 

    首先, 通过翻阅源码,我们来整理一下mybatis进行持久化操作时重要的几个类:

  • SqlSessionFactoryBuilder:build方法创建SqlSessionFactory实例。

  • SqlSessionFactory:创建SqlSession实例的工厂。

  • SqlSession:用于执行持久化操作的对象,类似于jdbc中的Connection。

  • SqlSessionTemplate:MyBatis提供的持久层访问模板化的工具,线程安全,可通过构造参数或依赖注入SqlSessionFactory实例。

 

    hibernate是与MyBatis类似的orm框架,这里与Hibernate进行一下对比,Hibernate中对于connection的管理,是通过以下几个重要的类:

  • SessionFactory:创建Session实例的工厂,类似于MyBatis中的SqlSessionFactory。

  • Session:用来执行持久化操作的对象,类似于jdbc中的Connection。

  • HibernateTemplate:Hibernate提供的持久层访问模板化的工具,线程安全,可通过构造参数或依赖注入SessionFactory实例。

 

    在日常的开发中,我们经常需要这样对MyBatis和Spring进行集成,把sqlSessionFactory交给Spring管理,通常情况下,我们这样配置:

[xml]  view plain  copy
  1. <code class="hljs javascript" style=""><bean id=<span class="hljs-string" style="">"sqlSessionFactory"</span> <span class="hljs-class" style=""><span class="hljs-keyword" style="">class</span></span>=<span class="hljs-string" style="">"org.mybatis.spring.SqlSessionFactoryBean"</span>>  
  2.     <span class="xml" style=""><span class="hljs-tag" style=""><<span class="hljs-name" style="">property</span> <span class="hljs-attr" style="">name</span>=<span class="hljs-string" style="">"dataSource"</span> <span class="hljs-attr" style="">ref</span>=<span class="hljs-string" style="">"dataSource"</span> /></span>  
  3. <span class="hljs-tag" style=""></<span class="hljs-name" style="">bean</span>></span></span></code>  

    通过上面的配置,Spring将自动创建一个SqlSessionFactory对象,其中使用到了org.mybatis.spring.SqlSessionFactoryBean,其 是MyBatis为Spring提供的用于创建SqlSessionFactory的类,将在Spring应用程序的上下文建议一下可共享的 MyBatis SqlSessionFactory实例,我们可以通过依赖注入将SqlSessionFactory传递给MyBatis的一些接口。

 

    如果通过Spring进行事务的管理,我们需要增加Spring注解的事务管理机制,如下配置:

[xml]  view plain  copy
  1. <code class="hljs javascript" style=""><bean id=<span class="hljs-string" style="">"transactionManager"</span> <span class="hljs-class" style=""><span class="hljs-keyword" style="">class</span></span>=<span class="hljs-string" style="">"org.springframework.jdbc.datasource.DataSourceTransactionManager"</span>>  
  2.     <span class="xml" style=""><span class="hljs-tag" style=""><<span class="hljs-name" style="">property</span> <span class="hljs-attr" style="">name</span>=<span class="hljs-string" style="">"dataSource"</span> <span class="hljs-attr" style="">ref</span>=<span class="hljs-string" style="">"dataSource"</span> /></span>  
  3. <span class="hljs-tag" style=""></<span class="hljs-name" style="">bean</span>></span></span>  
  4.    
  5. <tx:annotation-driven/></code>  

    

    这样,我们就可以使用Spring @Transactional注解,进行事务的控制,表明所注释的方法应该在一个事务中运行。 Spring将在事务成功完成后提交事务,在事务发生错误时进行异常回滚,而且,Spring会将产生的MyBatis异常转换成适当的 DataAccessExceptions,从而提供具体的异常信息。

 

    下面,我们通过分析SqlSessionUtils中getSession的源码,来详细的了解一下sqlSession的产生过程,源码如下:

[java]  view plain  copy
  1. <code class="hljs java" style=""><span class="hljs-function" style=""><span class="hljs-keyword" style="">public</span> <span class="hljs-keyword" style="">static</span> SqlSession <span class="hljs-title" style="">getSqlSession</span><span class="hljs-params" style="">(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator)</span> </span>{  
  2.    
  3.   notNull(sessionFactory, <span class="hljs-string" style="">"No SqlSessionFactory specified"</span>);  
  4.   notNull(executorType, <span class="hljs-string" style="">"No ExecutorType specified"</span>);  
  5.    
  6.   SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory);  
  7.    
  8.   <span class="hljs-keyword" style="">if</span> (holder != <span class="hljs-keyword" style="">null</span> && holder.isSynchronizedWithTransaction()) {  
  9.     <span class="hljs-keyword" style="">if</span> (holder.getExecutorType() != executorType) {  
  10.       <span class="hljs-keyword" style="">throw</span> <span class="hljs-keyword" style="">new</span> TransientDataAccessResourceException(<span class="hljs-string" style="">"Cannot change the ExecutorType when there is an existing transaction"</span>);  
  11.     }  
  12.    
  13.     holder.requested();  
  14.    
  15.     <span class="hljs-keyword" style="">if</span> (logger.isDebugEnabled()) {  
  16.       logger.debug(<span class="hljs-string" style="">"Fetched SqlSession ["</span> + holder.getSqlSession() + <span class="hljs-string" style="">"] from current transaction"</span>);  
  17.     }  
  18.    
  19.     <span class="hljs-keyword" style="">return</span> holder.getSqlSession();  
  20.   }  
  21.    
  22.   <span class="hljs-keyword" style="">if</span> (logger.isDebugEnabled()) {  
  23.     logger.debug(<span class="hljs-string" style="">"Creating a new SqlSession"</span>);  
  24.   }  
  25.    
  26.   SqlSession session = sessionFactory.openSession(executorType);  
  27.    
  28.   <span class="hljs-comment" style="">// Register session holder if synchronization is active (i.e. a Spring TX is active)</span>  
  29.   <span class="hljs-comment" style="">//</span>  
  30.   <span class="hljs-comment" style="">// Note: The DataSource used by the Environment should be synchronized with the</span>  
  31.   <span class="hljs-comment" style="">// transaction either through DataSourceTxMgr or another tx synchronization.</span>  
  32.   <span class="hljs-comment" style="">// Further assume that if an exception is thrown, whatever started the transaction will</span>  
  33.   <span class="hljs-comment" style="">// handle closing / rolling back the Connection associated with the SqlSession.</span>  
  34.   <span class="hljs-keyword" style="">if</span> (isSynchronizationActive()) {  
  35.     Environment environment = sessionFactory.getConfiguration().getEnvironment();  
  36.    
  37.     <span class="hljs-keyword" style="">if</span> (environment.getTransactionFactory() <span class="hljs-keyword" style="">instanceof</span> SpringManagedTransactionFactory) {  
  38.       <span class="hljs-keyword" style="">if</span> (logger.isDebugEnabled()) {  
  39.         logger.debug(<span class="hljs-string" style="">"Registering transaction synchronization for SqlSession ["</span> + session + <span class="hljs-string" style="">"]"</span>);  
  40.       }  
  41.    
  42.       holder = <span class="hljs-keyword" style="">new</span> SqlSessionHolder(session, executorType, exceptionTranslator);  
  43.       bindResource(sessionFactory, holder);  
  44.       registerSynchronization(<span class="hljs-keyword" style="">new</span> SqlSessionSynchronization(holder, sessionFactory));  
  45.       holder.setSynchronizedWithTransaction(<span class="hljs-keyword" style="">true</span>);  
  46.       holder.requested();  
  47.     } <span class="hljs-keyword" style="">else</span> {  
  48.       <span class="hljs-keyword" style="">if</span> (getResource(environment.getDataSource()) == <span class="hljs-keyword" style="">null</span>) {  
  49.         <span class="hljs-keyword" style="">if</span> (logger.isDebugEnabled()) {  
  50.           logger.debug(<span class="hljs-string" style="">"SqlSession ["</span> + session + <span class="hljs-string" style="">"] was not registered for synchronization because DataSource is not transactional"</span>);  
  51.         }  
  52.       } <span class="hljs-keyword" style="">else</span> {  
  53.         <span class="hljs-keyword" style="">throw</span> <span class="hljs-keyword" style="">new</span> TransientDataAccessResourceException(  
  54.             <span class="hljs-string" style="">"SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization"</span>);  
  55.       }  
  56.     }  
  57.   } <span class="hljs-keyword" style="">else</span> {  
  58.     <span class="hljs-keyword" style="">if</span> (logger.isDebugEnabled()) {  
  59.       logger.debug(<span class="hljs-string" style="">"SqlSession ["</span> + session + <span class="hljs-string" style="">"] was not registered for synchronization because synchronization is not active"</span>);  
  60.     }  
  61.   }  
  62.    
  63.   <span class="hljs-keyword" style="">return</span> session;  
  64. }</code>  

    上面的getSession方法,会从Spring的事务管理器中获取一个SqlSession或创建一个新的SqlSession,将试图从当前事务中得到一个SqlSession,然后,如果配置有事务管理器的工厂并且Spring 的事务管理器是活跃的,它将会锁定当前事务的SqlSession,保证同步。主要是通过以下几个步骤进行SqlSession的创建:

  1. 它会首先获取SqlSessionHolder,SqlSessionHolder用于在TransactionSynchronizationManager中保持当前的SqlSession。

  2. 如果holder不为空,并且holder被事务锁定,则可以通过holder.getSqlSession()方法,从当前事务中获取sqlSession,即 Fetched SqlSession from current transaction。

  3. 如果不存在holder或没有被事务锁定,则会创建新的sqlSession,即 Creating a new SqlSession,通过sessionFactory.openSession()方法。

  4. 如果当前线程的事务是活跃的,将会为SqlSession注册事务同步,即 Registering transaction synchronization for SqlSession。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值