文档章节

MyBatis整合Spring-->SqlSession获取

tara_qri
 tara_qri
发布于 2015/11/01 14:44
字数 740
阅读 1194
收藏 7

目的

MyBatis在执行SQL语句时,都需要创建一个SqlSession,但是这里还需要与Spring的事务进行整合,那么SqlSession是怎么创建的呢?下面就来分析一下。

上一章节已经分析MapperProxy代理类中,具体执行代码,实际MyBatis调用就是使用的SqlSession入口,就来看看SqlSession具体是哪个类。

通过DEBUG,可知是SqlSessionTemplate类。

根据前一章节的查询来分析,上图就是SqlSessionTemplate类的查询方法,就来看一下sqlSessionProxy属性。

根据SqlSessionTemplate类的构造器可以看出,sqlSessionProxy属性是一个代理类为SqlSessionInterceptor,看一下代理类的回调方法。

明显这里有获取SqlSession,这应该就是DefaultSqlSession,来看看,是怎么获取到的?

public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
    notNull(sessionFactory, "No SqlSessionFactory specified");
    notNull(executorType, "No ExecutorType specified");
    // 使用Spring来获取资源
    SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory);
    // 已存在SqlSessionHolder,直接获取
    if (holder != null && holder.isSynchronizedWithTransaction()) {
      if (holder.getExecutorType() != executorType) {
        throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction");
      }
      holder.requested();
      if (logger.isDebugEnabled()) {
        logger.debug("Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction");
      }
      return holder.getSqlSession();
    }
    if (logger.isDebugEnabled()) {
      logger.debug("Creating a new SqlSession");
    }
    // 新建SqlSession 
    SqlSession session = sessionFactory.openSession(executorType);
    // Register session holder if synchronization is active (i.e. a Spring TX is active)
    //
    // Note: The DataSource used by the Environment should be synchronized with the
    // transaction either through DataSourceTxMgr or another tx synchronization.
    // Further assume that if an exception is thrown, whatever started the transaction will
    // handle closing / rolling back the Connection associated with the SqlSession.
    if (isSynchronizationActive()) {
      Environment environment = sessionFactory.getConfiguration().getEnvironment();
      if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {
        if (logger.isDebugEnabled()) {
          logger.debug("Registering transaction synchronization for SqlSession [" + session + "]");
        }
        // 与Spring绑定
        holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
        bindResource(sessionFactory, holder);
        registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
        holder.setSynchronizedWithTransaction(true);
        holder.requested();
      } else {
        if (getResource(environment.getDataSource()) == null) {
          if (logger.isDebugEnabled()) {
            logger.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");
          }
        } else {
          throw new TransientDataAccessResourceException(
              "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
        }
      }
    } else {
      if (logger.isDebugEnabled()) {
        logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");
      }
    }
    return session;
  }

这里就是获取当前的事务里的SqlSession,并与Spring绑定。

DefaultSqlSessionFactory工厂的openSession方法。

DefaultSqlSessionFactory工厂的openSessionFromDataSource方法。首先获取环境信息,获取事务工厂(SpringManagedTransactionFactory),这个就是在MyBatis整合Spring的实现(1)中4.6创建的。还有Executor也是代理对象,把MyBatis中的配置的拦截器代理进来,这个以后再分析。

根据数据源(DataSource)创建了一个SpringManagedTransaction事务。

上图可以发现,这是个代理对象,最后new DefaultSqlSession对象。

最后通过方法反射调用DefaultSqlSession类的下图方法。

总结

MyBatis的SqlSession是在Dao层获取的,Service层只是Spring管理了事务,Dao层MyBatis通过与Spring的整合,来使用Spring的事务,所以目前的配置与Spring的整合,只能支持默认的SIMPLE类型(每次执行一个SQL都需要数据库编译),如果需要使用BATCH(批量新增,只需编译一次SQL,本次添加的SQL都按编译时的SQL来进行添加),这样明显提升效率。批量时,也想使用Spring的事务管理,就需要扩展SqlSession,这里以后再分析。

© 著作权归作者所有

tara_qri
粉丝 10
博文 48
码字总数 21496
作品 1
海淀
私信 提问
关于MyBatis sqlSession的一点整理

原文地址:关于MyBatis sqlSession的一点整理 工作中,需要学习一下MyBatis sqlSession的产生过程,翻看了mybatis-spring的源码,阅读了一些mybatis的相关doc,对mybatis sqlSession有了一些...

Realfighter
2015/01/04
31.5K
1
mybatis-spring:mybatis在spring中的使用

当我们想在 spring 项目中使用 mybatis 的时候就需要 mybatis-spring 了,它可以让 spring 完美的整合 mybatis 代码。使用这个类库中的类,spring 将会加载必要的 mybatis 工厂类和 session ...

非摩尔根
01/08
67
0
Mybatis之执行SQL过程

概述 MyBatis执行Sql的一个过程当中是怎么样的呢,涉及到了那些类呢,让我们不妨来一一过一遍。MyBatis的用法可以采用纯MyBatis、或者使用Spring集成的用法。 纯MyBatis 原生MyBatis对外暴露...

cregu
03/31
22
0
杂谈——Mybatis一二级缓存简单详解

先说缓存,合理使用缓存是优化中最常见。将从数据库中查询出来的数据放入缓存(内存)中,每次查询数据时,先判断缓存区中是否存在数据,如果存在,就从缓存区中获取数据,如果不存在,就从数...

一只野生饭卡丘
2018/12/23
0
0
MyBatis系列目录--7. Mybatis与Spring最佳整合

转载请注明出处哈:http://carlosfu.iteye.com/blog/2238662 1. 整合思路 (1) SqlSessionFactory由Spring作为单例管理 (2) spring和mybatis整合生成代理对象,使用SqlSessionFactory创建SqlSe...

付磊-起扬
2015/09/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS7.6中安装使用fcitx框架

内容目录 一、为什么要使用fcitx?二、安装fcitx框架三、安装搜狗输入法 一、为什么要使用fcitx? Gnome3桌面自带的输入法框架为ibus,而在使用ibus时会时不时出现卡顿无法输入的现象。 搜狗和...

技术训练营
昨天
5
0
《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
昨天
8
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
昨天
10
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
昨天
6
0
PHP+Ajax微信手机端九宫格抽奖实例

PHP+Ajax结合lottery.js制作的一款微信手机端九宫格抽奖实例,抽奖完成后有收货地址添加表单出现。支持可以设置中奖概率等。 奖品列表 <div class="lottery_list clearfix" id="lottery"> ......

ymkjs1990
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部