专栏首页后端开发随笔深入浅出mybatis之与spring集成

深入浅出mybatis之与spring集成

写在前面

在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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深入浅出mybatis之映射器

    映射器是MyBatis中最核心的组件之一,在MyBatis 3之前,只支持xml映射器,即:所有的SQL语句都必须在xml文件中配置。而从MyBatis 3开始...

    2Simple
  • Spring Boot集成MyBatis的2种方式

    最近总是有同事和技术群的朋友提问在Spring Boot中使用MyBatis时遇到的问题,大多数问题总结起来就是对MyBatis和Spring框架不熟悉的原因导...

    2Simple
  • 常用Java数据库连接池

    在这里所谓的数据库连接是指通过网络协议与数据库服务之间建立的TCP连接。通常,与数据库服务进行通信的网络协议无需由应用程序本身实现,原因有三:

    2Simple
  • 流水线救赎:Spinnaker如何塑造SAP卓越的交付

    作为一名负责卓越交付的现场可靠性工程师(Site Reliability Engineer,SRE),可靠的部署对我来说很重要。我已经在SAP工作了一段时间,我...

    CNCF
  • python库Camelot从pdf抽取表格数据

    首先,让我们看一个简单的例子:eg.pdf,整个文件只有一页,这一页中只有一个表格,如下:

    周小董
  • CDH5弃用的项目

    Fayson
  • cvxopt 示例简单讲解

    Cvxopt 是基于 Python 语言的用于解决凸优化问题的免费包,可以用于求解纳什均衡问题的最优策略,好用但是不容易理解,

    杨熹
  • 图说:从全球172个地区国庆,看世界独立进程

    大数据文摘
  • Laravel5.1 框架分页展示实现方法实例分析

    本文实例讲述了Laravel5.1 框架分页展示实现方法。分享给大家供大家参考,具体如下:

    砸漏
  • 八成调查对象乘过“黑车”,呼吁市场放开

    随着上海、北京等地交通部门对各种专车服务进行重点治理,关于“专车”和“黑车”的讨论即成为市场与监管博弈的又一个热点话题。腾讯科技《企鹅智酷》近日对25829名网...

    腾讯大讲堂

扫码关注云+社区

领取腾讯云代金券