MyBatis整合Spring

Stella981
• 阅读 848

目的

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

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

MyBatis整合Spring

MyBatis整合Spring

通过DEBUG,可知是SqlSessionTemplate类。

MyBatis整合Spring

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

MyBatis整合Spring

MyBatis整合Spring

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

MyBatis整合Spring

明显这里有获取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绑定。

MyBatis整合Spring

DefaultSqlSessionFactory工厂的openSession方法。

MyBatis整合Spring

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

MyBatis整合Spring

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

MyBatis整合Spring

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

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

MyBatis整合Spring

总结

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
springmvc+Mybatis整合中sqlSession的创建问题
spring/springmvcmybatis在整合时,可以在applicationContent.xml文件中进行spring,springmvc,事务管理,数据库连接池等以及与Mybatis整合的配置,当然也可以分开配置各自的xml文件。在mybatisconfig.xml中主要进行一些别名,查询的分页方式的配置。例如:applicationCo
Stella981 Stella981
3年前
MyBatis接口(Bean)与配置信息(Mapper)绑定
目的MyBatis的XML配置文件解析成JAVA类并在内存中存储,但是在程序运行时需要对应的类去调用,而相应的调用类还没有实例化,现在流行的都是使用Spring去管理需要的对象,Spring提供2种方式,分别为XML与注解。下面来分析调用类的实例化及与配置绑定。1XML方式<bean id"menuMapper" cl
Easter79 Easter79
3年前
SSM_基于传统web项目
1.这是一个单模块的项目!有四个配置文件,mybaits,spring。springmvc,web.xml!2.web.xml配置文件,导入spring和springmvc的配置文件,spring配置文件中,获取sqlsession,以及关联mybatis的mpper(增删改查)文件3.mybatis的配置文件则可以不用写
Stella981 Stella981
3年前
SSM_基于传统web项目
1.这是一个单模块的项目!有四个配置文件,mybaits,spring。springmvc,web.xml!2.web.xml配置文件,导入spring和springmvc的配置文件,spring配置文件中,获取sqlsession,以及关联mybatis的mpper(增删改查)文件3.mybatis的配置文件则可以不用写
Easter79 Easter79
3年前
SqlSessionFactory
MyBatis的持久化解决方案将用户从原始的JDBC访问中解放出来,开发无需关注底层数据库的连接、数据的访问、事务控制等操作,将应用层从底层的JDBCAPI中抽取出来。MyBatis中常用的对象有SqlSessionFactory和SqlSession。1、SqlSessionFactorySqlSessionFactory是MyBatis的关键对象
Stella981 Stella981
3年前
Invalid property 'driver' of bean class [org.apache.commons.dbcp.BasicDataSource]
Spring整合MyBatis!main方法测试,出现异常:!(https://oscimg.oschina.net/oscnet/up5532e35c99469d9cfcd2bec483942cb367e.png)一堆错,很懵逼!别慌,慢慢分析,也许错误很简单;先分析一下applicationContext.xml文件
Stella981 Stella981
3年前
Mybatis学习——Mybatis核心配置
MyBatis的核心配置在使用MyBatis框架时,设计两个核心的d对象:SqlSessionFactory和SqlSession.SqlsessionFactorySqlSessionFactory是单个数据库映射关系经过编译后的内存镜像,其主要作用用来创建SqlSession对象,SqlS