目录

写在前面

在Java世界,AOP编程是非常流行的模式,大大降低了功能业务与核心业务之间的代码耦合度。而说到AOP,Spring更是业界主流实现框架。

MyBatis作为ORM框架,既可以独立使用,当然也不可免俗地可以与Spring集成在一起使用。

特别是在已经使用Spring框架的应用程序中,如果需要使用MyBatis作为ORM组件时,就必然需要将二者集成在一起。

实际上,MyBatis与Spring集成,本质上就是将MyBatis中的相应组件交给Spring容器进行管理,使得我们可以按照Spring方式来使用MyBatis。

详细配置

既然MyBatis与Spring集成时是将其组件交给Spring进行管理,是如何实现的呢?

实际上,集成MyBatis与Spring需要使用通过mybatis-spring这个组件来实现。

<!-- mybatis集成spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${version.mybatis.spring}</version>
</dependency>

具体是哪些组件要交给Spring托管呢?

1.dataSource(数据源)

数据源通常以连接池方式使用,如:C3P0,Druid等。

druid数据源配置示例(详见:https://github.com/alibaba/druid ) 如下:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<property name="filters" value="stat" />
<property name="maxActive" value="20" />
<property name="initialSize" value="1" />
<property name="maxWait" value="60000" />
<property name="minIdle" value="1" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="20" />
<property name="asyncInit" value="true" />
</bean>

2.sqlSessionFactory(Session工厂)

在独立使用MyBatis时,sqlSessionFactory是通过SqlSessionFactoryBuilder构建的。

// 从xml配置中构建sessionFactory
String resource = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

而与Spring集成时,sqlSessionFactory直接交给Spring管理。

实际上就是在Spring中使用SqlSessionFactoryBean对MyBatis的sqlSessionFactory进行了包装。

<!-- 配置sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>

3.Mapper(映射器)

MyBatis本身支持2种映射器(XML映射器和接口映射器),与Spring集成时2种映射器的注册方式不同。

(1)注册XML映射器

XML映射器在注册SqlSessionFactoryBean时通过属性mapperLocations指定。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 注册xml映射器 -->
<property name="mapperLocations" value="classpath*:org/chench/test/mybatis/mapper/**/*.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>

另外,在注册xml映射器时,可以同时在Spring中声明一个sqlSession对象,用于执行xml映射器中配置的CRUD操作。

注意:

  • 这里在Spring中注册sqlSession对象并不是MyBatis的sqlSession对象,而是SqlSessionTemplate。
  • SqlSessionTemplate是MyBatis-Spring的核心,这个类负责管理MyBatis的SqlSession, 调用MyBatis映射器的SQL方法, 翻译异常等。
  • SqlSessionTemplate是线程安全的, 可以被多个DAO所共享使用。
  • 当调用SQL方法时, SqlSessionTemplate将会保证使用的SqlSession是和当前Spring的事务相关的。此外,它管理SqlSession的生命周期,包含必要的关闭,提交或回滚操作。使用示例如下:
// 使用spring提供的sqlSession
SqlSession sqlSession = (SqlSession) context.getBean("sqlSession");
Test test = sqlSession.selectOne("org.chench.test.mybatis.mapper.selectOneTest", 1);
logger.info("test: {}", test); test.setName(new Date().getTime() + "_haha");
sqlSession.update("org.chench.test.mybatis.mapper.updateOneTest", test);
//注意: 使用spring管理的sqlSession时,不允许手动提交事务
//sqlSession.commit();

(2)注册接口映射器

<bean id="testMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 独立注册每一个映射器接口 -->
<property name="mapperInterface" value="org.chench.test.mybatis.mapper.impl.TestMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

实际上,在注册接口映射器时无需手动注册每一个映射器,使用MapperScannerConfigurer可以实现注册指定包路径下的所有映射器接口。

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="org.chench.test.mybatis.mapper.impl" />
</bean>

使用举例:

// 当使用接口映射器时,直接获取映射器接口Bean进行CRUD操作
TestMapper testMapper = context.getBean(TestMapper.class);
Test test = testMapper.selectOneTest(1);
logger.info("test: {}", test); test.setName("heihei");
testMapper.updateOneTest(test);

4.TransactionManager(事务管理器)

一个使用MyBatis-Spring的主要原因是它允许MyBatis参与到Spring的事务管理中。

而不是给MyBatis创建一个新的特定的事务管理器,MyBatis-Spring利用了存在于Spring中的 DataSourceTransactionManager。

一旦Spring的PlatformTransactionManager配置好了,你可以在Spring中以你通常的做法来配置事务,@Transactional注解和AOP样式的配置都是支持的。

在事务处理期间,一个单独的SqlSession对象将会被创建和使用。当事务完成时,这个session会以合适的方式提交或回滚。

一旦事务创建之后,MyBatis-Spring将会透明的管理事务。在你的DAO类中就不需要额外的代码了。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 开启注解方式控制事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />

注意: 对于事务管理器的使用,与MyBatis注册映射器方式不同而不同!

(1)如果MyBatis使用xml映射器,可以使用编程式地控制事务。

// 编程控制事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); PlatformTransactionManager txManager = (PlatformTransactionManager) context.getBean("transactionManager");
TransactionStatus status = txManager.getTransaction(def);
try {
sqlSession.update("org.chench.test.mybatis.mapper.updateOneTest", test);
txManager.commit(status);
} catch (Exception e) {
txManager.rollback(status);
e.printStackTrace();
}

(2)如果MyBatis的映射器为接口,则可以使用注解方式管理事务(需要在Spring中配置开启注解方式控制事务)。

// 这是一个事务型操作,使用注解方式控制事务
@Transactional
@Update("update test set name=#{name},descr=#{descr},url=#{url},update_time=now() where id=#{id}")
public Integer updateOneTest(Test test);

关于MyBatis与Spring集成的详细例子:https://gitee.com/cchanghui/test-mybatis.git

【参考】

[1]. http://www.mybatis.org/spring/

[2]. http://www.mybatis.org/spring/zh/sqlsession.html

深入浅出mybatis之与spring集成的更多相关文章

  1. 因此mybatis最好与spring集成起来使用

    单独使用mybatis是有很多限制的(比如无法实现跨越多个session的事务),而且很多业务系统本来就是使用spring来管理的事务,因此mybatis最好与spring集成起来使用. spring ...

  2. MyBatis 学习-与 Spring 集成篇

    根据官方的说法,在 ibatis3,也就是 Mybatis3 问世之前,Spring3 的开发工作就已经完成了,所以 Spring3 中还是没有对 Mybatis3 的支持.因此由 Mybatis 社 ...

  3. MyBatis操作指南-与Spring集成(基于注解)

  4. Spring集成MyBatis的使用-使用SqlSessionTemplate

    Spring集成MyBatis的使用 Spring集成MyBatis,早期是使用SqlSessionTemplate,当时并没有用Mapper映射器,既然是早期,当然跟使用Mapper映射器是存在一些 ...

  5. 重构Mybatis与Spring集成的SqlSessionFactoryBean(1)

    一般来说,修改框架的源代码是极其有风险的,除非万不得已,否则不要去修改.但是今天却小心翼翼的重构了Mybatis官方提供的与Spring集成的SqlSessionFactoryBean类,一来是抱着试 ...

  6. Java Persistence with MyBatis 3(中国版) 第五章 与Spring集成

    MyBatis-Spring它是MyBatis子模块框.它用来提供流行的依赖注入框架Spring无缝集成. Spring框架是一个基于依赖注入(Dependency Injection)和面向切面编程 ...

  7. Spring集成MyBatis框架

    Java在写数据库查询时,我接触过四种方式: 1.纯Java代码,引用对应的数据库驱动包,自己写连接与释放逻辑(可以用连接池) 这种模式实际上性能是非常不错的,但是使用起来并不是非常方便:一是要手工为 ...

  8. Quartz学习——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(四)

    当任何时候觉你得难受了,其实你的大脑是在进化,当任何时候你觉得轻松,其实都在使用以前的坏习惯. 通过前面的学习,你可能大致了解了Quartz,本篇博文为你打开学习SSMM+Quartz的旅程!欢迎上车 ...

  9. SSM框架开发web项目系列(五) Spring集成MyBatis

    前言 在前面的MyBatis部分内容中,我们已经可以独立的基于MyBatis构建一个数据库访问层应用,但是在实际的项目开发中,我们的程序不会这么简单,层次也更加复杂,除了这里说到的持久层,还有业务逻辑 ...

随机推荐

  1. 自学Aruba之添加黑名单Blacklists方法

    点击返回:自学Aruba之路点击返回:自学Aruba集锦 07 自学Aruba之添加黑名单Blacklists方法 方法一:页面添加方式,临时添加黑名单(禁止入网60min)方法二:命令行添加方式,临 ...

  2. 自学Python之路-Python并发编程+数据库+前端

    自学Python之路-Python并发编程+数据库+前端 自学Python之路[第一回]:1.11.2 1.3

  3. pycharm 中的 全局搜索(ctrl+shift+f) 功能无法使用的原因

    全局搜索的时候Ctrl+Shift+F按键失灵,有的时候可以,有时又不行了,百思不得其解. 在網上搜索很多人說是搜狗输入法的快捷键冲突了,但是我的电脑用的是微软自带的输入法 后来打开微软的输入法设置发 ...

  4. shell中,2>&1详解

    我们在Linux下经常会碰到nohup command>/dev/null 2>&1 &这样形式的命令.首先我们把这条命令大概分解下,首先就是一个nohup表示当前用户和系 ...

  5. Python By 360、小米

    小米 乱谈Python并发 说实话,我一直觉得PHP真的是最好的语言,不仅养活了一大批PHP程序员,同时还为安全人员提供了大量的就业机会.然而,令人唏嘘的是,安全界很多人其实是吃着Python的饭,操 ...

  6. bzoj4869: [Shoi2017]相逢是问候(欧拉函数+线段树)

    这题是六省联考的...据说数据还出了点锅,心疼六省选手QAQ 首先要知道扩展欧拉定理... 可以发现每次区间操作都会使模数进行一次phi操作,而一个数最多取logp次phi就会变成1,这时后面的指数就 ...

  7. Vue+Django2.0 restframework打造前后端分离的生鲜电商项目(3)

    1.drf前期准备 1.django-rest-framework官方文档 https://www.django-rest-framework.org/ #直接百度找到的djangorestframe ...

  8. 最短路 次短路 k短路(k很小)

    最短路 luogu 3371 https://www.luogu.org/problemnew/show/P3371 #include <cstdio> #include <cstd ...

  9. java 分隔函数split("",-1)的用途

    转: java 分隔函数split("",-1)的用途 2017年12月14日 11:37:58 jaryle 阅读数:8517   1.如果字符串最后一位有值,则没有区别, 2. ...

  10. Luogu P4248 [AHOI2013]差异

    题目链接 \(Click\) \(Here\) 神仙题.或者可能我太菜了没见过后缀数组的骚操作,然后就被秀了一脸\(hhhhh\) \[\sum\limits_{1<=i < j < ...