Spring | 整合 MyBatis

Spring | 整合 MyBatis

原始的 MyBatis 开发步骤

  1. 建表
  2. 创建与表结构对应的实体类
  3. 在 MyBatis 配置文件中创建实体类的别名,方便在映射文件中使用
  4. 创建 DAO 层接口
  5. 编写映射文件实现接口
  6. 在 MyBatis 配置文件中注册映射文件
  7. 调用接口方法
@Test
public void test() {
	// 获取 SqlSession
	InputStream is = MyBatisTest.class.getClassLoader().getResourceAsStream("mybatis.xml");
	SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
	SqlSession session = factory.openSession();

	// 获取接口的实现类对象,这个对象是 MyBatis 通过动态代理生成的实现类的对象
	UserDao mapper = session.getMapper(UserMapper.class);

	// 通过实现类对象调用接口的方法
	try {
		List<User> users = mapper.findAll();
		for(User user : users) {
			System.out.println(user);
		}
	} finally {
		session.close();
	}
}

可以看到,使用 MyBatis 原始的开发步骤会存在配置繁琐和代码冗余的问题,例如,需要配置大量的实体类别名,以及大量的 Mapper 文件注册,在执行接口中的方法之前需要先获取 SqlSessionFactoryBuilderSqlSessionFactorySqlSession 等对象,最后需要手动关闭 SqlSession

Spring 整合 MyBatis

总体思路

  1. 将 MyBatis 配置文件转移到 Sping 配置文件中,主要是解决连接池、实体类别名、注册 Mapper 文件的配置
  2. 封装获取 SqlSessionFactory 的系列代码

环境搭建

引入一下依赖,注意 Spring 整合 MyBatis 的相关 jar 包是由 MyBatis 给出的

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.2.6.RELEASE</version>
</dependency>

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>2.0.4</version>
</dependency>

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.12</version>
</dependency>

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.43</version>
</dependency>

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.4</version>
</dependency>

编码实现

转移配置文件

在配置文件中主要配置一下内容:

  1. 数据源信息,使用的连接池
  2. SqlSessionFactory 对象纳入 IOC 容器管理
  3. 实体类所在的包、Mapper 文件的路径、DAO 接口的路径
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!--配置连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/cap?characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>

        <!--创建SqlSessionFactory SqlSessionFactoryBean-->
        <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!-- 指定实体类所在的包 -->
            <property name="typeAliasesPackage" value="com.yusael.entity"/>
            <!--指定映射文件的路径-->
            <property name="mapperLocations">
                <list>
                    <value>classpath:cool/yzt/dao/*Mapper.xml</value>
                </list>
            </property>
        </bean>

        <!--创建DAO对象 MapperScannerConfigure-->
        <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
            <!--指定DAO接口放置的包-->
            <property name="basePackage" value="cool.yzt.dao"/>
        </bean>

</beans>

使用

Spring 帮我们接管了 MyBatis 的很多操作,需要我们自己编码实现的内容有

  1. 数据库表
  2. 实体类
public class User implements Serializable {
    private Integer id;
    private String name;
    private String password;
    // getter setter
}
  1. DAO 接口
public interface UserDAO {
    public void insert(User user);
}
  1. 映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cool.yzt.dao.UserDAO">
    <insert id="insert">
        insert into user (name,passwprd) values(#{name}, #{password})
    </insert>
</mapper>
  1. 在 Service 层调用 DAO 接口,这里以单元测试代替
@Test
public void test() {
    // 获取工厂
    ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
    // 获取DAO接口的代理实现类对象
    UserDAO userDAO = (UserDAO) ctx.getBean("userDAO");
    User user = new User();
    user.setName("xiaojr");
    user.setPassword("999999");
    // 执行insert操作
    userDAO.insert(user);
}

细节问题

Spring 与 Myabatis 整合后,为什么 DAO 不提交事务,但是数据能够插入数据库中?

  • 可以这样说,谁控制了 Connection 谁就控制了事务
  • 在此之前,使用 MyBatis 提供的连接池获取 Connection,底层 Connection.setAutoCommit(false),需要手动提交
  • 我们选择外部的 Druid(C3P0、DBCP)作为连接池,所有的连接都是从连接池获得,也就是说连接池控制着 Connection 和事务,底层 Connection.setAutoCommit(true),一条 SQL 完成自动提交,不需要手动提交事务
  • 在实战中,对于多条增删改语句的执行,我们依然会手动控制事务的提交和回滚,而 Spring 为我们提供了事务控制的解决方案

参考

孙哥说Spring5

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://yzt.cool/archives/spring整合mybatis