MyBatis框架的学习(六)

本文将手把手教你如何使用MyBatis整合Spring,这儿,我本人使用的MyBatis是MyBatis3.2.7这个版本,Spring是Spring4.1.3这个版本。读者只要学会这两个版本的框架整合之后,其他版本之间的整合就一通百通了。

整合思路

MyBatis整合Spring的思路如下:

  1. SqlSessionFactory对象应该放到spring容器中作为单例存在。
  2. 传统Dao的开发方式中,应该从spring容器中获得sqlsession对象。
  3. Mapper代理形式中,应该从spring容器中直接获得mapper的代理对象。
  4. 数据库的连接以及数据库连接池事务管理都交给spring容器来完成。

整合需要的jar包

MyBatis整合Spring所需的jar包如下:

  1. Spring的jar包。
  2. Mybatis的jar包。
  3. Spring+Mybatis的整合包,即mybatis-spring-1.2.2.jar
  4. MySql的数据库驱动jar包。
  5. 数据库连接池的jar包。

我整理出来的MyBatis与Spring整合全部jar包(包括springmvc):
MyBatis框架的学习(六)

整合的步骤

下面我将按照下面整合的步骤来整合MyBatis与Spring:

  1. 第一步:创建一个java工程。
  2. 第二步:导入jar包(上面提到的jar包)。
  3. 第三步:编写mybatis的配置文件——SqlMapConfig.xml。
  4. 第四步:编写Spring的配置文件。
    • 数据库连接及连接池
    • 事务管理(暂时可以不配置)
    • sqlsessionFactory对象,配置到spring容器中
    • mapeer代理对象或者是dao实现类配置到spring容器中
  5. 第五步:编写Dao或者mapper.xml映射文件。
  6. 第六步:测试。

按照上面的步骤来整合MyBatis与Spring的话,一般来说,MyBatis的核心配置文件——SqlMapConfig.xml的内容就应是:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置pojo别名 -->
    <typeAliases>
        <!-- <typeAlias type="cn.itheima.mybatis.po.User" alias="user"/> -->
        <!-- 扫描包的形式创建别名,别名就是类名,不区分大小写 -->
        <package name="cn.itheima.mybatis.po" />
    </typeAliases>

    <!-- 加载mapper文件 -->
    <mappers>
        <!-- resource是基于classpath来加载的 -->
        <mapper resource="sqlmap/user.xml" />
    </mappers>
</configuration>

    MyBatis框架的学习(六)
    Spring核心配置文件——application-context.xml的内容就应是:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        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-4.0.xsd
                            http://www.springframework.org/schema/context 
                            http://www.springframework.org/schema/context/spring-context-4.0.xsd
                            http://www.springframework.org/schema/aop 
                            http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 
                            http://www.springframework.org/schema/tx 
                            http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
                            http://www.springframework.org/schema/util 
                            http://www.springframework.org/schema/util/spring-util-4.0.xsd">
    
        <!-- 加载配置文件 -->
        <context:property-placeholder location="classpath:db.properties" />
        <!-- 数据库连接池 -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="driverClassName" value="${jdbc.driver}" />
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <property name="maxActive" value="10" />
            <property name="maxIdle" value="5" />
        </bean>
    
        <!-- SqlSessionFactory的配置 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 配置数据库连接池 -->
            <property name="dataSource" ref="dataSource"></property>
            <!-- 加载mybatis的核心配置文件 -->
            <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml"></property>
        </bean>
    </beans>

      MyBatis框架的学习(六)
      其中db.properties配置文件中的内容是:

      jdbc.driver=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
      jdbc.username=root
      jdbc.password=yezi

        Dao层的开发

        MyBatis整合Spring之后,就要开发Dao层了, Dao层的开发有三种实现方式:

        1. 传统Dao层的开发方式。
        2. 使用mapper代理形式开发方式。
        3. 使用扫描包配置mapper代理

        下面我依次来讲解这三种实现方式。

        传统Dao层的开发方式

        传统Dao层的开发是使用接口+实现类的方式来完成的,Dao层实现类需要继承SqlsessionDaoSupport类,就像下面这样:
        MyBatis框架的学习(六)
        以上Dao层实现类——UserDaoImpl.java的内容为:

        // 原始Dao开发方式,须继承抽象类SqlSessionDaoSupport
        public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
        
            @Override
            public User getUserById(int id) {
                SqlSession sqlSession = getSqlSession();
                // 根据id来查询用户信息
                User user = sqlSession.selectOne("test.getUserById", id);
                // 不要手动关闭SqlSession,如果你手动关闭了,就会抛出一个异常
                // sqlSession.close();
                return user;
            }
        
            @Override
            public List<User> getUserByName(String username) {
                // 创建一个SQLSession对象
                SqlSession sqlSession = getSqlSession();
                // 执行查询
                List<User> list = sqlSession.selectList("getUserByName", username);
                // 不要手动释放资源
                // sqlSession.close();
                return list;
            }
        
            @Override
            public void insertUser(User user) {
                // 创建一个SQLSession对象
                SqlSession sqlSession = getSqlSession();
                // 插入用户
                sqlSession.insert("insertUser", user);
                // 提交事务
                sqlSession.commit();
                // 不要手动释放资源
                // sqlSession.close();
            }
        
        }

          注意:以上每个方法中不要手动关闭SqlSession,如果你手动关闭了,就会抛出一个异常
          接着要把Dao层实现类——UserDaoImpl.java配置到Spring容器中,如下:

          <!-- 传统dao的配置方法 -->
          <bean id="userDaoImpl" class="cn.itheima.mybatis.dao.impl.UserDaoImpl">
              <!-- 注入sqlSessionFactory这个属性 -->
              <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
          </bean>

            最后我们就要进行测试了,在如下UserDaoTest单元测试类中
            MyBatis框架的学习(六)
            编写一个testGetUserById单元测试方法,如下:

            public class UserDaoTest {
            
                private ApplicationContext applicationContext;
            
                @Before
                public void init() {
                    // 初始化Spring容器
                    applicationContext = new ClassPathXmlApplicationContext("classpath:spring/application-context.xml");
                }
            
                @Test
                public void testGetUserById() {
                    UserDao userDao = applicationContext.getBean(UserDao.class); // 通过类型去装配
                    // UserDao userDao = (UserDao) applicationContext.getBean("userDaoImpl");
                    User user = userDao.getUserById(24);
                    System.out.println(user);
                }
            
            }

              运行testGetUserById方法,有可能出现以下异常:
              MyBatis框架的学习(六)
              异常信息已用红框框出,怎么解决呢?聪明的小伙伴们肯定知道了,有可能你之前UserDaoImpl实现类的getUserById方法是写成这样的:

              @Override
              public User getUserById(int id) {
                  SqlSession sqlSession = getSqlSession();
                  // 根据id来查询用户信息
                  User user = sqlSession.selectOne("getUserById", id);
                  // 不要手动关闭SqlSession,如果你手动关闭了,就会抛出一个异常
                  // sqlSession.close();
                  return user;
              }

                要解决该异常,只须将以上方法修改为:

                @Override
                public User getUserById(int id) {
                    SqlSession sqlSession = getSqlSession();
                    // 根据id来查询用户信息
                    User user = sqlSession.selectOne("test.getUserById", id);
                    // 不要手动关闭SqlSession,如果你手动关闭了,就会抛出一个异常
                    // sqlSession.close();
                    return user;
                }

                  为什么要这样修改呢?我截图一张,你就应该明白了。
                  MyBatis框架的学习(六)
                  讲完传统Dao层的开发方式后,下面我来讲第二种实现方式——使用mapper代理形式开发Dao层。

                  Mapper代理形式开发Dao层

                  首先开发mapper接口及相对应的mapper.xml映射文件,如下所示:
                  MyBatis框架的学习(六)
                  然后配置mapper代理,即需要在application-context.xml文件中添加如下配置:

                  <!-- mapper代理形式dao的配置 -->
                  <!-- 第一种方式,配置代理对象 -->
                  <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
                      <!-- 设置代理的mapper接口,即为哪一个接口创建代理对象 -->
                      <property name="mapperInterface" value="cn.itheima.mybatis.mapper.UserMapper"></property>
                      <!-- 由于MapperFactoryBean这个类继承自SqlSessionDaoSupport类,所以要注入sqlSessionFactory这个属性 -->
                      <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
                  </bean>

                    整体效果看起来就像下面这样:
                    MyBatis框架的学习(六)
                    最后我们就要进行测试了,在UserDaoTest单元测试类中编写如下方法:

                    @Test
                    public void testUserMapper() {
                        UserMapper userMapper = applicationContext.getBean(UserMapper.class);
                        User user = userMapper.getUserById(24);
                        System.out.println(user);
                    }
                    • 1
                    • 2
                    • 3
                    • 4
                    • 5
                    • 6

                    小结:使用Mapper代理形式开发Dao层,在实际开发中显然不经用,因为万一有很多很多mapper接口需要配置其代理对象呢?所以下面我就要讲开发Dao层的第三种实现方式了,它在实际开发中就经常用到。

                    扫描包形式配置mapper代理

                    使用扫描包的形式配置mapper代理来开发Dao层,需要在application-context.xml文件中配置一个包扫描器,即在该文件中添加如下配置:

                    <!-- 第二种方式,配置包扫描器 -->
                    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                        <!-- 配置要扫描的包 -->
                        <property name="basePackage" value="cn.itheima.mybatis.mapper" />
                    </bean>

                      注意:

                      1. 该扫描器会自动去Spring容器中去找你已经初始化好后的sqlSessionFactory, 所以在此并不需要配置。
                      2. 如果要扫描多个包,那么使用半角逗号分隔
                      3. 使用扫描包的形式配置mapper代理之后,每个mapper代理对象的id就是类名,且首字母小写

                      这样,整体效果看起来就像下面这样:
                      MyBatis框架的学习(六)
                      并且如果在application-context.xml文件中配置了扫描包之后,在SqlMapConfig.xml配置文件中就不需要以下配置了:

                      <!-- 加载mapper文件 -->
                      <mappers>
                          <!-- resource是基于classpath来加载的 -->
                          <mapper resource="sqlmap/user.xml" />
                      </mappers>

                        MyBatis框架的学习(六)
                        至此,MyBatis整合Spring我就已总结完了。

                        本文将手把手教你如何使用MyBatis整合Spring,这儿,我本人使用的MyBatis是MyBatis3.2.7这个版本,Spring是Spring4.1.3这个版本。读者只要学会这两个版本的框架整合之后,其他版本之间的整合就一通百通了。