# 整合 MyBatis

​ 一提到 Mybatis,我就想到在做数据库课设早期我被写 JDBC 这种大量冗余的底层代码所折磨,直到学习了 Mybatis 之后,就去掉了大量的代码,只需要写 SQL 语句和编写 xml 配置文件即可。

​ 如此好的东西,Spring 作为整合的框架,肯定必须拿下。

# 基本配置

1. 导入 jar 包

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

2. 要和 Spring 一起使用 MyBatis, 需要在 Spring 应用上下文中定义至少两样东西:一个 SqlSessionFactory 和至少一个数据映射器类。

在 spring 的 xml 文件中配置

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

​ 这里的 dataSource 相当于是传统 jdbc 的替代品,传统 jdbc 每次连接都需要数据库驱动器、用户名和密码才可以建立连接,会产生很多不必炫耀的开销;

​ 而这里的 dataSource 则是数据源建立多个数据库连接,这些数据库连接会保存在数据库连接池中,当需要访问数据库时,只需要从数据库连接池中 获取空闲的数据库连接,当程序访问数据库结束时,数据库连接会放回数据库连接池中。


然后这里回顾一下之前 mybatis 中 sqlsession 的创建方法

public class MyBatisUtil {
    private  static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            // 使用 mybatis 第一步,获取 sqlSessionFactory 对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 既然有了 SqlFactory,就可以从从中获取 SQLSession 实例
    //SQLSession 完全包含了面向数据库执行 sql 的所有方法。
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}

我们会创建一个工具类实现 SqlSessionFactoryBuilder 来创建 SqlSessionFactory ,然后获取 SQLSession。

而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来创建,而其核心就是 SQLSessionTemplate。

<!-- 注册 sqlSessionTemplate , 关联 sqlSessionFactory-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <!-- 利用构造器注入,因为没有 set 方法进行注入 -->
    <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>

# 整合方法一

1. 引入 Spring 配置文件 beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<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">

2. 配置数据源替换 mybaits 的数据源

<!-- 配置数据源:数据源有非常多,可以使用第三方的,也可使使用 Spring 的 -->
<!-- 这里的可以把这些 values 放在 properties 文件中 -->
<bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql://localhost:3306/lpl?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>
   <property name="username" value="root"/>
   <property name="password" value="123456"/>
</bean>

3. 配置 SqlSessionFactory,关联 MyBatis

<!-- 配置 SqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
   <property name="dataSource" ref="dataSource"/>
   <!-- 关联 Mybatis,mybatis 的 xml 文件中还可保留一些配置,如 alias, 但是实际上现在完全可以不需要这个 mybatis-config.xml 这个文件了 -->
   <property name="configLocation" value="classpath:mybatis-config.xml"/>
   <property name="mapperLocations" value="classpath:com/Meteor/dao/*.xml"/>
</bean>

4. 注册 sqlSessionTemplate,关联 sqlSessionFactory;

<!-- 注册 sqlSessionTemplate , 关联 sqlSessionFactory-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
   <!-- 利用构造器注入 -->
   <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>

5. 增加 Dao 接口的实现类;私有化 sqlSessionTemplate

public class UserMapperImpl implements UserMapper {
   //sqlSession 不用我们自己创建了,Spring 来管理
   private SqlSessionTemplate sqlSession;
   public void setSqlSession(SqlSessionTemplate sqlSession) {
       this.sqlSession = sqlSession;
  }
   public List<User> selectUser() {
       UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       return mapper.selectUser();
  }
   
}

6. 注册 bean 实现

<bean id="userMapper" class="com.Meteor.dao.UserDaoImpl">
   <property name="sqlSession" ref="sqlSession"/>
</bean>

7. 测试

@Test
   public void test2(){
       ApplicationContext context = newClassPathXmlApplicationContext("beans.xml");
       UserMapper mapper = (UserMapper) context.getBean("userMapper");
       List<User> user = mapper.selectUser();
       System.out.println(user);
  }

# 整合方法二

​ dao (Mapper) 继承 Support 类,直接利用 getSqlSession () 获得,然后直接注入 SqlSessionFactory . 比起方式 1 , 不需要管理 SqlSessionTemplate , 而且对事务的支持更加友好。可跟踪源码查看。

测试:

1. 将我们上面写的 UserDaoImpl 修改一下

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
   public List<User> selectUser() {
       UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
       return mapper.selectUser();
  }
}

2. 修改 bean 的配置

<bean id="userMapper" class="com.Meteor.dao.UserMapperImpl">
   <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

3. 测试

@Test
public void test2(){
   ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
   UserMapper mapper = (UserMapper) context.getBean("userMapper");
   List<User> user = mapper.selectUser();
   System.out.println(user);
}

# 总结

dao 层文件变化

​ 现在 dao 层会有 3 个文件。

UserMapper 接口,UserMapper.xml 用于编写 sql 语句,UserMapperImpl 是实现了 SqlSession,实现了 UserMapper 接口的增强类。

这样子看起来似乎比只用 mybatis 的时候多了一个 UserMapperImpl。但是当时为了实现 sqlSession,是将这部分编写成一个公共工具类,然后拿到 service 层去实现,实际上封装部分做的并没有这里好。