官网地址:http://mybatis.org/spring/zh/index.html

当我们想在 spring 项目中使用 mybatis 的时候就需要 mybatis-spring 了,它可以让 spring 完美的整合 mybatis 代码。使用这个类库中的类,spring 将会加载必要的 mybatis 工厂类和 session 类。 这个类库也提供一个简单的方式来注入 mybatis 数据映射器和 SqlSession 到业务层的 bean 中。 而且它也会处理事务, 翻译 MyBatis 的异常到 Spring 的 DataAccessException 异常(数据访问异常)中

我们先走一个简单例子,再在基础上扩展

一、例子

1、添加依赖

使用 mybatis-spring 模块,需要添加 mybatis-spring-x.x.x.jar

  1. <dependency>
  2. <groupId>org.mybatis</groupId>
  3. <artifactId>mybatis-spring</artifactId>
  4. <version>1.3.2</version>
  5. </dependency>

同时加上 mybatis-x.x.x.jar 包和相关数据库连接包,spring 的依赖添加上 spring-context 和 spring-jdbc,如果是 web 项目,再加上 web 相关的 jar 包即可

2、创建 SqlSessionFactoryBean

我们在使用 mybatis 的时候,最关键的是去使用 SqlSession 去执行映射的 SQL 语句。而 SqlSession 是通过 SqlSesionFactory 来获取的。而 SqlSessionFactory 的实例则是由SqlSessionFactoryBuilder 从 XML 配置文件或一个预先定制的 Configuration 的实例构建出来的

现在,我们是要在 spring 上整合 mybatis,需要把 SqlSessionFactory 的创建和 注入交给 spring容器,在 mybatis-spring 中 SqlSessionFactory 的创建交给了 SqlSessionFactoryBean

我们在项目中创建一个 spring 的配置文件,添加相关配置,加上 SqlSessionFactoryBean 的配置
application-mybatis.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/context
  8. http://www.springframework.org/schema/context/spring-context.xsd">
  9. <!-- 使用注解声明 -->
  10. <context:component-scan base-package="com.brave"/>
  11. <!-- 加载属性资源 -->
  12. <context:property-placeholder location="classpath*:conf/*.properties"></context:property-placeholder>
  13. <!-- 配置 SqlSessionFactoryBean -->
  14. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  15. <property name="dataSource" ref="dataSource" />
  16. <!-- mybatis 配置文件位置(默认配置的话,可以不用)-->
  17. <property name="configLocation" value="classpath:conf/mybatis/mybatis-config.xml"></property>
  18. <!-- 配置映射器文件 -->
  19. <property name="mapperLocations" value="classpath*:com/brave/dao/mapper/*Mapper.xml" />
  20. </bean>
  21. <!-- 配置数据源 -->
  22. <!-- 这里使用的是 druid 连接池,需要另外导入 druid.jar -->
  23. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
  24. <property name="driverClassName" value="${jdbc.driver}" />
  25. <property name="url" value="${jdbc.url}" />
  26. <property name="username" value="${jdbc.username}" />
  27. <property name="password" value="${jdbc.password}" />
  28. </bean>
  29. <!-- 事务管理器 -->
  30. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  31. <property name="dataSource" ref="dataSource" />
  32. </bean>
  33. </beans>

要注意 SqlSessionFactoryBean 实现了 Spring 的 FactoryBean 接口。 这就说明了由 Spring 最终创建的 bean 不是 SqlSessionFactoryBean 本身。 而是工厂类的 getObject()返回的方法的结果。这种情况下,Spring 将会在应用启动时为你 创建 SqlSessionFactory 对象,然后将它以 SqlSessionFactory 为名来存储。在 Java 中, 相同的代码是: SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); SqlSessionFactory sessionFactory = factoryBean.getObject(); 但是一般我们不直接使用 SqlSessionFactoryBean 或 SqlSessionFactory。因为 session 工厂将会被注入到映射器中 或其它扩展了 SqlSessionDaoSupport 的 DAO(Data Access Object,数据访问对象)中

SqlSessionFactory有三个属性

  • dataSource 属性是必须的,配置数据源信息
  • configLocation 属性用来指定 MyBatis 的 XML 配置文件路径,如果基本的 MyBatis 配置需要改变(通常这会是 或的部分)
  • mapperLocations 属性用来指定映射器文件的资源位置

mapperLocations 可以配置多个位置

  1. <property name="mapperLocations">
  2. <list>
  3. <value>classpath*:conf/mybatis/**/*Mapper.xml</value>
  4. <value>classpath*:conf/com/brave/**/*Mapper.xml</value>
  5. </list>
  6. </property>

3、使用 SqlSessionTemplate

在 mybatis 中,我们使用 SqlSessionFactory 来创建 SqlSession。获取了一个 session 之后,使用它来执行映射的 SQL 语句、提交或回滚连接,最后当不再需要它的时候关闭 session。
使用 mybatis-spring 之后,就不需要直接使用 SqlSessionFactory 了,因为你的 bean 可以通过一个线程安全的 SqlSession 来注入,基于 spring 的事务配置来自动提交、回滚、关闭 session。

1)SqlSessionTemplate

SqlSessionTemplate 是 mybatis-spring 的核心。它负责管理 mybatis 的 SqlSession, 调用 mybatis 的 SQL 方法、翻译异常。它是线程安全的,可以被多个 DAO 所共享使用。
当调用 SQL 方法时,包含从映射器 getMapper()方法返回的方法,SqlSessionTemplate 将会保证使用的 SqlSession 是和当前 Spring 的事务相关的。它管理这 session 的生命周期,包含必要的关闭,提交或回滚操作。

SqlSessionTemplate 对象可以使用 SqlSessionFactory 作为构造方法的参数来创建

  1. <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  2. <constructor-arg index="0" ref="sqlSessionFactory" />
  3. <!-- 配置了BATCH 表示所有的语句可以批量操作 -->
  4. <constructor-arg index="1" value="BATCH" />
  5. </bean>

SqlSessionTemplate 实现了 SqlSession 接口,不用再代码中对 mybatis 的 SqlSession 进行替换,直接在 Dao bean中直接注入这个 SqlSession 属性就可以了

  1. @Repository
  2. public class UpmsUserDaoImpl implements UpmsUserDao {
  3. @Autowired
  4. private SqlSession sqlSession;
  5. @Override
  6. public UpmsUser selectOne(Long userId) {
  7. return sqlSession.selectOne("com.brave.dao.UpmsUserDao.selectOne", userId);
  8. }
  9. @Override
  10. public List<UpmsUser> selectUser(UpmsUser upmsUser) {
  11. return sqlSession.selectList("com.brave.dao.UpmsUserDao.selectUser", upmsUser);
  12. }
  13. @Override
  14. public int insertUser(UpmsUser upmsUser) {
  15. return sqlSession.insert("com.brave.dao.UpmsUserDao.insertUser", upmsUser);
  16. }
  17. }

这里附上我的映射文件 upmsUserMapper.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace="com.brave.dao.UpmsUserDao">
  6. <resultMap type="com.brave.model.UpmsUser" id="upmsUser">
  7. <id column="user_id" property="userId"/>
  8. <result column="loginname" property="loginname"/>
  9. <result column="password" property="password"/>
  10. <result column="realname" property="realname"/>
  11. <result column="phone" property="phone"/>
  12. <result column="email" property="email"/>
  13. <result column="is_locked" property="locked"/>
  14. <result column="gmt_create" property="gmtCreate"/>
  15. <result column="gmt_modified" property="gmtModified"/>
  16. </resultMap>
  17. <select id="selectOne" resultMap="upmsUser">
  18. select * from upms_user where user_id = #{userId}
  19. </select>
  20. <select id="selectUser" resultMap="upmsUser">
  21. select * from upms_user
  22. <where>
  23. <if test="loginname != null and loginname != '' ">
  24. loginname like #{loginname}
  25. </if>
  26. <if test="realname != null and realname != '' ">
  27. and realname like #{realname}
  28. </if>
  29. </where>
  30. </select>
  31. <insert id="insertUser">
  32. insert into upms_user (user_id,loginname,password,realname,is_locked)
  33. value(#{userId},#{loginname},#{password},#{realname},#{locked})
  34. </insert>
  35. </mapper>

使用 Junit 生成测试类

  1. @RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
  2. @ContextConfiguration ("/conf/spring/applicationContext*.xml")
  3. public class UpmsUserDaoImplTest {
  4. @Autowired
  5. private UpmsUserDao upmsUserDao;
  6. @Test
  7. public void testSelectOne() {
  8. System.out.println(upmsUserDao.selectOne(10001L).toString());
  9. }
  10. @Test
  11. public void testSelectUser() {
  12. UpmsUser user = new UpmsUser();
  13. user.setLoginname("zou");
  14. user.setUserId(2L);
  15. List<UpmsUser> upmsUsers = upmsUserDao.selectUser(user);
  16. for (UpmsUser upmsUser : upmsUsers) {
  17. System.out.println(upmsUser.toString());
  18. }
  19. }
  20. @Test
  21. @Transactional //声明需要事务
  22. public void testInsertUser() {
  23. UpmsUser upmsUser = new UpmsUser();
  24. upmsUser.setUserId(10002L);
  25. upmsUser.setLoginname("zou");
  26. upmsUser.setPassword("123456");
  27. upmsUser.setLocked(false);
  28. int n = upmsUserDao.insertUser(upmsUser);
  29. System.out.println("插入" + n + "行");
  30. }
  31. }

2) SqlSessionDaoSupport

SqlSessionDaoSupport 是一个抽象的支持类,用来提供 SqlSession。getSqlSession()方法可以得到一个 SqlSessionTemplate

  1. public class UpmsUserDaoImpl2 extends SqlSessionDaoSupport implements UpmsUserDao {
  2. @Override
  3. public UpmsUser selectOne(Long userId) {
  4. return getSqlSession().selectOne("com.brave.dao.UpmsUserDao.selectOne", userId);
  5. }
  6. }

SqlSessionDaoSupport 需要设置一个 sqlSessionFactory 或 sqlSessionTemplate 属性
假如是 UpmsUserDaoImpl2 继承了 SqlSessionDaoSupport:

  1. <bean id="upmsUserDaoImpl" class="com.brave.dao.UpmsUserDaoImpl2">
  2. <property name="sqlSessionFactory" ref="sqlSessionFactory" />
  3. </bean>

可以创建一个公用的 SuperDao 去继承 SqlSessionDaoSupport,为 SuperDao 设置 sqlSessionFactory 属性,然后让其他 dao 去继承 SuperDao,这样就不用每个 dao 都去设置这个属性了

  1. public class SuperDao extends SqlSessionDaoSupport {
  2. @Autowired
  3. public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
  4. super.setSqlSessionFactory(sqlSessionFactory);
  5. }
  6. }

不过通常我们更常用 MapperFactoryBean(只需要接口,不用实现类),因为它不需要额外的代码。但是如果需要在 DAO 中做其它非 MyBatis 的工作或需要具体的类,那么这个类就很有用了。

二、事务

mybatis-spring 允许 mybatis 参与到 spring 的事务管理中。利用了存在于 Spring 中的 DataSourceTransactionManager,而不是创建一个新的特定的事务管理器

一旦 Spring 的 PlatformTransactionManager 配置好了,可以在 spring 中以通常的做法来配置事务。@Transactional 注解和 AOP 样式的配置都是支持的。在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。

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

1、标准配置

要 开 启 Spring 的 事 务 处 理 , 在 Spring 的 XML 配 置 文 件 中 简 单 创 建 一 个 DataSourceTransactionManager 对象:

  1. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  2. <property name="dataSource" ref="dataSource" />
  3. </bean>

三、注入映射器

在 mybatis 中,我们可以创建一个来绑定映射的语句的接口映射器(实际上也就是我们的 dao 接口),在映射文件的命名空间与我们的映射器完全限定名一致,映射语句id名就是映射器的方法名,这样我们可以不用实现这个映射器,通过 sqlSession 获取映射器,直接使用 sql 方法

  1. UpmsUserDao upmsUserDao = sqlSession.getMapper(UpmsUserDao.class);
  2. UpmsUse upmsUse = upmsUserDao.selectOne(10002L);

为了代替手工使用 SqlSessionDaoSupport 或 SqlSessionTemplate 编写数据访问对象 (DAO)的代码,mybatis-spring 也提供了一个动态代理的实现:MapperFactoryBean。这个类可以让你直接注入 数据映射器接口 到你的 service 层 bean 中。当使用映射器时,直接调用就可以了,不需要实现 DAO接口,因为 mybatis-spring 将会为你创建代理。

使用注入的映射器代码,在 mybatis、spring 或 mybatis-spring 上面不会有直接的依赖。 MapperFactoryBean 创建的代理控制开放和关闭 session,会翻译任意的异常到 spring 的 DataAccessException 异常中。此外,如果需要或参与到一个已经存在活动事务中,代理将会开启一个新的 spring 事务。

1、MapperFactoryBean

想要直接使用 数据映射器接口,先添加 MapperFactoryBean 到 spring 中:

  1. <bean id="upmsUserMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  2. <property name="mapperInterface" value="com.brave.mapper.UpmsUserMapper" />
  3. <property name="sqlSessionFactory" ref="sqlSessionFactory" />
  4. </bean>

MapperFactoryBean 创建的代理类实现了 UpmsUserMapper 接口,并且注入到应用程序中。 因为代理创建在运行时环境中,那么指定的映射器必须是一个接口,而不是一个具体的实现类。

如果 XML 映射器文件在类路径的位置和映射器类相同时,它会被 MapperFactoryBean 自动解析,否则你需要在 SqlSessionFactoryBean 的 mapperLocations 或是在 mybatis 的配置文件中指明映射文件的位置

这里附上映射文件,这里的命名空间一定要是映射器的完全限定名

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper
  3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <!-- 这里的命名空间一定要是映射器的完全限定名 -->
  6. <mapper namespace="com.brave.mapper.UpmsUserMapper">
  7. <!-- 这里的id与映射器的方法一致 -->
  8. <select id="selectUser" resultType="com.brave.model.UpmsUser">
  9. select * from upms_user
  10. </select>
  11. </mapper>

接口映射器 UpmsUserMapper.java

  1. public interface UpmsUserMapper {
  2. List<UpmsUser> selectUser();
  3. }

然后我们在应用程序逻辑中可以直接使用

  1. @Service
  2. public class UpmsUserServiceImpl implements UpmsUserService {
  3. @Autowired
  4. private UpmsUserMapper upmsUserMapper;
  5. @Override
  6. public List<UpmsUser> listUser() {
  7. return upmsUserMapper.selectUser();
  8. }
  9. }

2、MapperScannerConfigurer

我们没有必要在 spring 的 XML 配置文件中注册所有的映射器。只用使用一个 MapperScannerConfigurer 即可,它会查找类路径下的映射器并自动将它们创建成 MapperFactoryBean

  1. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  2. <property name="basePackage" value="com.brave.mapper" />
  3. </bean>

这样就不用每个 mapper 都配置一个 MapperFactoryBean 了

basePackage 属性是让你为映射器接口文件设置基本的包路径。 可以使用 分号 或 逗号 作为分隔符设置多于一个的包路径。每个映射器将会在指定的包路径中递归地被搜索到

3、@MapperScan 和 mybatis:scan

另外还有两种扫描映射器的方法

1) mybatis:scan 元素

mybatis:scan 元素将在特定的以逗号分隔的包名列表中搜索映射器 mapper 接口。 要使用这个元素需要添加以下的 schema 声明

  1. <beans xmlns="http://www.springframework.org/schema/beans"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd
  6. http://mybatis.org/schema/mybatis-spring
  7. http://mybatis.org/schema/mybatis-spring.xsd">
  8. <mybatis:scan base-package="com.brave.mapper" />
  9. </beans>

2) @MapperScan

如果使用基于java的配置,可以使用@MapperScan 注解来扫描映射器 Mapper 接口。 @MapperScan mybatis:scan/ 工作方式
相同,并且也提供了对应的自定义选项
在 spring-boot 项目中可能会使用到

  1. @SpringBootApplication
  2. @MapperScan("com.brave.mapper")
  3. public class App {
  4. public static void main(String[] args) {
  5. SpringApplication.run(App.class, args);
  6. }
  7. }