美文网首页spring boot
第 10 章 MyBatis 与 Spring 的整合

第 10 章 MyBatis 与 Spring 的整合

作者: 辽A丶孙悟空 | 来源:发表于2019-08-27 19:26 被阅读0次

    在前面章节中,分别讲解了 Spring 和 MyBatis 的相关知识,然而在实际的项目开发中, Spring 与 MyBatis 都是整合在一起使用的。 在掌握了 MyBatis 的使用后,本章将对 MyBatis 与 Spring 的整合内容进行详细讲解。

    整合环境搭建
    • 准备所需 JAR 包

    要实现 MyBatis 与 Spring 的整合,很明显需要这两个框架的 JAR 包,但是只使用这两个框架中所提供的 JAR 包是不够的,还需要其他的 JAR 包来配合使用,整合时所需准备的 JAR 包具体如下。

    1. Spring 框架所需的 JAR 包
      Spring 框架所需要准备的 JAR 包共 10 个,其中包括: 4 个核心模块 JAR , AOP 开发使用的 JAR , JDBC 和事务的 JAR (其中核心容器依赖的 commons-Iogging 的 JAR 在 MyBatis 框 架的 lib 包中已经包含,所以这里不必再加入),具体如下所示。


    2. MyBatis 框架所需的 JAR 包
      MyBatis 框架所需要准备的 JAR 包共 13 个,其中包括:核心包 mybatis-3.4.2.jar 以及其解压文件夹中 lib 目录中的所有 JAR ,具体如下所示。


    3. MyBatis 与 Spring 整舍的中间 JAR
      由于 MyBatis 3 在发布之前, Spring 3 就已经开发完成,而 Spring 团队既不想发布基于 MyBatis 3 的非发布版本的代码,也不想长时间的等待,所以 Spring 3 以后,就没有对 MyBatis 3 进行支持。 为了满足 MyBatis 用户对 Spring 框架的需求, MyBatis 社区自己开发了一个用于整合这两个框架的中间件:MyBatis-Spring。
      在这里我是用的版本为 mybatis-spring一1.3.1.jar , 希望大家也同样下载该版本。 此版本的 JAR 包可以通过如下链接获取 ''http://mvnrepository.com/artifact/org.mybatis/mybatis-spring/1.3.1 "。
    4. 数据库驱动 JAR 包
      我所使用的数据库驱动包为 mysql-connector-java-5.1.40-bin.jar。


    5. 数据源所需 JAR 包
      整合时所使用的是 DBCP 数据源,所以需要准备 DBCP 和连接池的 JAR 包,具体如下所示。


    • 编写配置文件

    在 Eclipse 中,创建一个名称为 mybatis_spring01 的 Web 项目,将上一小节中所准备的全部 JAR 包添加到项目的 lib 目录中,并发布到类路径下。
    在项目的 src 目录下,分别创建 db.properties 文件、 Spring 的配置文件以及 MyBatis 的配置文件,文件分别如下所示。

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
    jdbc.username=root
    jdbc.password=root
    jdbc.maxTotal=30 
    jdbc.maxIdle=10
    jdbc.initialSize=5 
    

    在文件中,除配置了连接数据库的基本 4 项外,还配置了数据库连接池的最大连接数 (maxTotal)、最大空闲连接数 (maxldle) 以及初始化连接数( initialSize )。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:aop="http://www.springframework.org/schema/aop" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx" 
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.3.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
      <!-- 读取 db.properties -->
      <context:property-placeholder location="classpath:db.properties"/>
      <!-- 配置数据源 -->
      <bean id="dataSource"
          class="org.apache.commons.dbcp2.BasicDataSource">
          <!-- 数据库驱动 -->
          <property name="driverClassName" value="${jdbc.driver}" />
          <!-- 连接数据库的 url -->
          <property name="url" value="${jdbc.url}" />
          <!-- 连接数据库的用户名 -->
          <property name="username" value="${jdbc.username}" />
          <!-- 连接数据库的密码 -->
          <property name="password" value="${jdbc.password}" />
          <!-- 最大连接数  -->
          <property name="maxTotal" value="${jdbc.maxTotal}" />
          <!-- 最大空闲连接  -->
          <property name="maxIdle" value="${jdbc.maxIdle}" />
          <!-- 初始化连接数  -->
          <property name="initalSize" value="${jdbc.initalSize}" />       
      </bean>
      <!-- 事务管理器,依赖于数据源  -->
      <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource" /> 
      </bean>
      <!-- 注册事务管理器驱动,开启事务注解  -->
      <tx:annotation-driven transaction-manager="transactionManager"/> 
      <!-- 配置MyBatis工厂  -->
      <bean id="sqlSeesionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
          <!-- 注入数据源  -->
          <property name="dataSource" ref="dataSource" />
          <!-- 指定核心配置文件  -->
          <property name="configLocation" value="classpath:mybatis-config.xml"></property>
      </bean>
    </beans> 
    

    在文件中,首先定义了读取 properties 文件的配置,然后配置了数据源,接下来配置了事务管理器并开启了事务注解,最后配置了 MyBatis 工厂来与 Spring 整合。 其中, MyBatis 工厂的作用就是构建 SqlSessionFactory,它是通过 mybatis-spring 包中提供的 org.mybatis.spring.SqlSessionFactoryBean 类来配置的。 通常,在配置时需要提供两个参数:一个是数据源, 另一个是 MyBatis 的配置文件路径。这样 Spring 的 loC 容器就会在初始化 id 为 sqISession Factory 的 Bean 时解析 MyBatis 的配置文件,并与数据源一同保存到 Spring 的 Bean 中。

    <?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>
      <!-- 使用扫描包的形式定义别名 -->
      <typeAliases>
          <package name="com.neuedu.po" />
      </typeAliases>
      <!-- 2.配置Mapper的位置 -->
      <mappers>
          <!-- .... -->
      </mappers>
    </configuration>
    

    由于在 Spring 中已经配置了数据源信息,所以在 MyBatis 的配置文件中就不再需要配置数据源信息。 这里只需要使用<typeAliases>和<mappers>元素来配置文件别名以及指定 Mapper 文件位置即可。
    此外,还需在项目的 src 目录下创建 log4j.properties 文件,该文件的编写可参考第 6 章的入门案例,也可将前面章节所创建的该文件复制到此项目中使用。

    传统 DAO 方式的开发整合

    上一小节已经完成了对 MyBatis 与 Spring 整合环境的搭建工作,可以说完成了这些配置后, 就已经完成了这两个框架大部分的整合工作。 接下来,本小节将通过传统 DAO 层开发的方式, 来演示这两个框架实际的整合使用。
    采用传统 DAO 开发方式进行 MyBatis 与 Spring 框架的整合时,我们需要编写 DAO 接口以及接口的实现类,并且需要向 DAO 实现类中注入 SqlSessionFactory ,然后在方法体内通过 SqlSessionFactory 创建 SqlSession。 为此,我们可以使用 mybatis-spring 包中所提供的 SqlSessionTemplate 类或 SqlSessionDaoSupport 类来实现此功能。 这两个类的描述如下。

    • SqlSessionTemplate: 是 mybatis-spring 的核心类,它负责管理 MyBatis 的 SqlSession , 调用 MyBatis 的 SOL 方法。当调用 SOL 方法时, SqlSessionTemplate 将会保证使用的 SqlSession 和当前 Spring 的事务是相关的。 它还管理 SqlSession 的生命周期,包含必要的关闭 、 提交和回滚操作。
    • SqlSessionDaoSupport: 是一个抽象支持类,它继承了 DaoSupport 类,主要是作为 DAO 的基类来使用 。 可以通过 SqlSessionDaoSupport 类的 getSqlSession() 方法来获取所需的 SqlSession。

    了解了传统 DAO 开发方式整合可以使用的两个类后,下面以 SqlSessionDaoSupport 类的使用为例,讲解传统的 DAO 开发方式整合的实现,其具体步骤如下。

    1. 实现持久层
      ( 1 )在 src 目录下,创建一个 com.neuedu.po 包,并在包中创建持久化类 Customer,在Customer 类中定义相关属性和方法后,文件如下所示。
    package com.neuedu.po;
    /**
    * 客户持久化类
    */
    public class Customer {
      private Integer id; //主键 id
      private String username; //客户名称
      private String jobs; //职业
      private String phone; //电话
      public Integer getId() {
          return id;
      }
      public void setId(Integer id) {
          this.id = id;
      }
      public String getUsername() {
          return username;
      }
      public void setUsername(String username) {
          this.username = username;
      }
      public String getJobs() {
          return jobs;
      }
      public void setJobs(String jobs) {
          this.jobs = jobs;
      }
      public String getPhone() {
          return phone;
      }
      public void setPhone(String phone) {
          this.phone = phone;
      }
      @Override
      public String toString() {
          return "Customer [id=" + id + ", username=" + username + ", jobs=" + jobs + ", phone=" + phone + "]";
      }
    }`
    

    ( 2 )在 com.neuedu.po 包中,创建映射文件 CustomerMapper.xml ,在该文件中编写根据 id 查询客户信息的映射语句,文件如下所示。

    <?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="com.neuedu.mapper.CustomerMapper">  
      <!-- 根据 id查询客户信息 -->
      <select id="findCustomerById" parameterType="Integer" resultType="customer">
          select * from t_customer where id = #{id}
      </select>
    </mapper>
    

    ( 3 )在 MyBatis 的配置文件 mybatis-config.xml 中,配置映射文件 CustomerMapper.xml 的位置,具体如下。

          <mapper resource="com/neuedu/po/CustomerMapper.xml"/>
    
    1. 实现 DAO 层
      ( 1 )在 src 目录下,创建一个 com.neuedu.dao 包,并在包中创建接口 CustomerDao,在接口中编写一个通过 id 查询客户的方法 findCustomerByld() ,文件如下所示。
    package com.neuedu.dao;
    import com.neuedu.po.Customer;
    public interface CustomerDao {
      // 通过id查询客户
      public Customer findCustomerByld(Integer id);
    }
    

    ( 2 )在 src 目录下,创建一个 com.neuedu.dao.impl 包,并在包中创建 CustomerDao 接口的实现类 CustomerDaoImpl ,编辑后文件如下所示。

    package com.neuedu.dao.impl;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    import com.neuedu.dao.CustomerDao;
    import com.neuedu.po.Customer;
    public class CustomerDaoImpl extends SqlSessionDaoSupport implements >CustomerDao {
      //通过id查询客户
      public Customer findCustomerByld(Integer id) {
          return this.getSqlSession().selectOne("com.neuedu.po.CustomerMapper.findCustomerById",id);
      }
    }
    

    在文件中, CustomerDaolmpl 类继承了 SqlSessionDaoSupport 类,并实现了 CustomerDao 接口 。 其中, SqlSessionDaoSupport 类在使用时需要一个 SqlSessionFactory 或 一个 SqlSessionTemplate 对象,所以需要通过 Spring 给 SqlSessionDaoSupport 类的子类对象注入一个 SqlSessionFactory 或 SqlSessionTemplate 。 这样,在子类中就能通过调用 SqlSessionDaoSupport 类的 getSqlSession() 方法来获取 SqlSession 对象,并使用 SqlSession 对象中的方法了 。
    ( 3 )在 Spring 的配置文件 applicationContext.xml 中,编写实例化 CustomerDaolmpl 的配置,代码如下所示。

      <!-- 实例化Dao -->
      <bean id="customerDao" class="com.neuedu.dao.impl.CustomerDaoImpl">
          <!-- 注入SqlSessionFactory 对象实例 -->
          <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
      </bean>
    

    上述代码创建了一个 id 为 customerDao 的 Bean ,并将 SqlSessionFactory 对象注入到了该 Bean 的实例化对象中 。

    1. 整合测试
      在 src 目录下,创建一个 com.neuedu.test 包,在包中创建测试类 DaoTest ,并在类中编写测试方法 findCustomerByldDaoTest() ,文件如下所示。
    package com.neuedu.test;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import com.neuedu.dao.CustomerDao;
    import com.neuedu.po.Customer;
    /**
    * DAO 测试类
    */
    public class DaoTest {
      @Test
      public void findCustomerByldDaoTest(){
          ApplicationContext act= new ClassPathXmlApplicationContext("applicationContext.xml");
          // 根据容器中Bean的id来获取指定的Bean
          CustomerDao customerDao= (CustomerDao) act.getBean("customerDao");
          Customer customer = customerDao.findCustomerByld(1);
          System.out.println(customer);
      }
    }
    

    在上述方法中 ,我们采用的是根据容器中 Bean 的 id 来获取指定 Bean 的方式。 有些人在通过其他一些参考资料学习时,可能还会看到另一种获取 Bean 的方式,即根据类的类型来获取 Bean 的实例 , 此种方式就是第 1 章中讲解的 Spring 另一种获取 Bean 的方式。 如果要采用这种方式,只需将获取Bean代码修改如下。

    CustomerDao customerDao = (CustomerDao) act.getBean(CustomerDao.class); 
    

    这样在获取 Bean 的实例时,就不再需要进行强制类型转换了。
    使用 JUnit4 执行上述方法后,控制台的输出结果如图所示。



    从图中可以看出,通过 CustomerDao 实例的 findCustomerByld()方法已经查询出了 id 为 1 的客户信息,这也就说明了 MyBatis 与 Spring 整合成功。

    Mapper 接口方式的开发整合

    在 MyBatis+Spring 的项目中,虽然使用传统的 DAO 开发方式可以实现所需功能,但是采用这种方式在实现类中会出现大量的重复代码,在方法中也需要指定映射文件中执行语句的 id , 并且不能保证编写时 id 的正确性(运行时才能知道)。 为此,我们可以使用 MyBatis 提供的另外 一种编程方式,即使用 Mapper 接口编程。 接下来的两个小节中,将讲解如何使用 Mapper 接口 方式来实现 MyBatis 与 Spring 的整合。

    • 基于 MapperFactoryBean 的整合

    MapperFactoryBean 是 MyBatis-Spring 团队提供的一个用于根据 Mapper 接口生成 Mapper 对象的类,该类在 Spring 配置文件中使用时可以配置以下参数。

    • mapperl nterface: 用于指定接口 。
    • SqlSessionFactory: 用于指定 SqlSessionFactory。
    • SqlSessionTemplate: 用于指定 SqlSessionT emplate。
      如果与SqlSessionFactory 同时设定,则只会启用 SqlSessionTemplate。

    了解了 MapperFactoryBean 类后,接下来通过一个具体的案例来演示如何通过 MapperFactoryBean 来实现 MyBatis 与 Spring 的整合,具体步骤如下。
    ( 1 )在 src 目录下,创建一个 com.neuedu.mapper 包,然后在该包中创建 CustomerMapper 接口以及对应的映射文件,编辑后文件如下所示。

    package com.neuedu.mapper;
    import com.neuedu.po.Customer;
    public interface CustomerMapper {
      // 通过id查询客户
      public Customer findCustomerByld(Integer id);
    }
    
    <?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="com.neuedu.mapper.CustomerMapper">  
      <!-- 根据 id查询客户信息 -->
      <select id="findCustomerById" parameterType="Integer" resultType="customer">
          select * from t_customer where id = #{id}
      </select>
    </mapper>
    

    从两个文件中可以看出,这两个文件的实现代码与前面小节中 CustomerDao 接口以及映射文件 CustomerMapper.xml 的实现代码基本相同,只是本案例与前面小节案例的区别在于,本案例将接口文件改名并与映射文件一起放在了 com.neuedu.mapper 包中。
    ( 2 )在 MyBatis 的配置文件中 ,引入新的映射文件,代码如下所示。

          <!-- Mapper 接口开发方式  -->
          <mapper resource="com/neuedu/mapper/CustomerMapper.xml"/>
    

    小提示:使用 Mapper 接口动态代理开发方式时,如果完全遵循了编写规范(请参见本节后面的手下留心) ,那么在配置文件中可以不引入映射文件。
    ( 3 )在 Spring 的配置文件中,创建一个 id 为 customerMapper 的 Bean ,代码如下所示。

      <!-- Mapper代理开发(基于MapperFactoryBean) -->
      <bean id="customerMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
          <property name="mapperInterface" value="com.neuedu.mapper.CustomerMapper" />
          <property name="sqlSessionFactory" ref="sqlSessionFactory" />
      </bean>
    

    上述配置代码为 MapperFactoryBean 指定了接口以及 SqlSessionFactory。
    ( 4 )在测试类 DaoTest 中,编写测试方法 findCustomerByldMapperTest() ,其代码如下所示。

      @Test
      public void findCustomerByldMapperTest(){
          ApplicationContext act= new ClassPathXmlApplicationContext("applicationContext.xml");
          // 根据容器中Bean的id来获取指定的Bean
          CustomerMapper customerMapper = (CustomerMapper) act.getBean(CustomerMapper.class); 
          Customer customer = customerMapper.findCustomerById(1);
          System.out.println(customer);
      }
    

    上述方法中,通过 Spring 容器获取了 CustomerMapper 实例,并调用了实例中的 findCustomerByld() 方法来查询 id 为 1 的客户信息。
    使用 JUnit4 执行上述方法后,控制台的输出结果如图所示。



    从图中可以看出,通过 Mapper 接口的方式,同样查询到了相应的客户信息。

    • 手下留心
      Mapper 接口编程方式只需要程序员编写 Mapper 接口(相当于 DAO 接口),然后由 MyBatis 框架根据接口的定义创建接口的动态代理对象,这个代理对象的方法体等同于前面小节中 DAO 接口的实现类方法。 虽然使用 Mapper 接口编程的方式很简单,但是在具体使用时还是需要遵循以下规范。
      ( 1 ) Mapper 接口的名称和对应的 Mapper.xml 映射文件的名称必须一致。
      ( 2 ) Mapper.xml 文件中的 namespace 与 Mapper 接口的类路径相同(即接口文件和映射文件需要放在同一个包中)。
      ( 3 ) Mapper 接口中的方法名和 Mapper.xml 中定义的每个 SQL 执行语句的 id 相同 。
      ( 4 ) Mapper 接口中方法的输入参数类型要和 Mapper.xml 中定义的每个 sql 的 parameterType 的类型相同 。
      ( 5 ) Mapper 接口方法的输出参数类型要和 Mapper.xml 中定义的每个 sql 的 resultType 的类型相同 。
      只要遵循了这些开发规范, MyBatis 就可以自动生成 Mapper 接口实现类的代理对象,从而简化我们的开发。
    • 基于 MapperScannerConfigurer 的整合

    在实际的项目中, DAO 层会包含很多接口,如果每一个接口都像前面小节中那样在 Spring 配置文件中配置,那么不但会增加工作量,还会使得 Spring 配置文件非常臃肿。 为此, MyBatis-Spring 团队提供了一种自动扫描的形式来配置 MyBatis 中的映射器一一采用 MapperScannerConfigurer 类。
    MapperScannerConfigurer 类在 Spring 配置文件中使用时可以配置以下几个属性。

    • basePackage: 指定映射接口文件所在的包路径,当需要扫描多个包时可以使用分号或逗 号作为分隔符。 指定包路径后,会扫描该包及其子包中的所有文件。
    • annotationClass: 指定了要扫描的注解名称,只有被注解标识的类才会被配置为映射器。
    • sqlSessionFactoryBeanName:指定在 Spring 中定义的 SqlSessionFactory 的 Bean 名称。
    • sqlSessionTemplateBeanName: 指定在 Spring 中定义的 SqlSessionTemplate 的 Bean 名称。 如果定义此属性,则sqlSessionFactoryBeanName 将不起作用。
    • markerlnterface: 指定创建映射器的接口 。

    MapperScannerConfigurer 的使用非常简单,只需要在 Spring 的配置文件中编写如下代码:

      <!-- Mapper代理开发(基于 MapperScannerConfigurer) -->
      <bean id="org.mybatis.spring.mapper.MapperScannerConfigurer">
          <property name="basePackage" value="com.neuedu.mapper"/>
      </bean>
    

    在通常情况下, MapperScannerConfigurer 在使用时只需通过 basePackage 属性指定需要扫描的包即可, Spring 会自动地通过包中的接口来生成映射器。 这使得开发人员可以在编写很少代码的情况下,完成对映射器的配置,从而提高开发效率。
    要验证上面的配置也很容易,只需将上述配置代码写入 Spring 的配置文件,并将前面小节中的第 ( 2 )步和第 ( 3 )步的代码注释掉,再次执行 findCustomerByldMapperTest() 方法进行测试即可。 方法执行后,会发现显示结果与前面小节中的结果一致。 由于篇幅有限,这里将不再展示,大家可自行测试。

    测试事务

    在 MyBatis+Spring 的项目中,事务是由 Spring 来管理的。 在前面小节中,我们已经配置了事务管理器,并开启了事务注解,但是现在还不能够确定事务的配置是否正确,以及事务管理能否生效。 接下来,本节将对如何测试项目中配置的事务进行详细讲解。
    在项目中,业务层( Service 层)既是处理业务的地方,又是管理数据库事务的地方。 要对事务进行测试,首先需要创建业务层,并在业务层编写添加客户操作的代码;然后在添加操作的代码后,有意地添加一段异常代码(如 int i = 1/0; )来模拟现实中的意外情况;最后编写测试方法,调用业务层的添加方法。这样,程序在执行到错误代码时就会出现异常。 在没有事务管理的情况下,即使出现了异常,数据也会被存储到数据表中;如果添加了事务管理,并且事务管理的配置正确,那么在执行上述操作时,所添加的数据将不能够插入到数据表中。
    下面对上述分析进行实际的编写测试,其具体的实现步骤如下。
    ( 1 )在 CustomerMapper 接口中,编写测试方法 addCustomer() ,代码如下所示。

      // 添加客户
      public void addCustomer(Customer customer);
    

    编写完接口中的方法后,在映射文件 CustomerMapper.xml 中编写执行插入操作的 SQL 配置,代码如下所示。

      <!-- 添加客户信息  -->
      <insert id="addCustomer">
          insert into t_customer(username,jobs,phone)
          values(#{username},#{jobs},#{phone})
      </insert>
    

    ( 2 )在 src 目录下,创建一个 com.neuedu.service 包,并在包中创建接口 CustomerService , 在接口中编写一个添加客户的方法 addCustomer() ,文件如下所示。

    package com.neuedu.service;
    import com.neuedu.po.Customer;
    public interface CustomerService {
      // 添加客户
      public void addCustomer(Customer customer);
    }
    

    ( 3 )在 src 目录下,创建一个 com.neuedu.service.impl 包,并在包中创建 CustomerService 接口的实现类 CustomerServicelmpl ,来实现接口中的方法,编辑后文件如下所示。

    package com.neuedu.service.impl;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import com.neuedu.mapper.CustomerMapper;
    import com.neuedu.po.Customer;
    import com.neuedu.service.CustomerService;
    @Service
    //@Transactional
    public class CustomerServicelmpl implements CustomerService {
      //注解注入CustomerMapper
      @Autowired
      private CustomerMapper customerMapper;
      //添加客户
      @Override
      public void addCustomer(Customer customer) {
          this.customerMapper.addCustomer(customer);
          int i = 1/0;//模拟添加操作后系统突然出现的异常问题        
      }
    }
    

    在文件中,使用了 Spring 的注解 @Service 来标识业务层的类,使用了@Transactional 注解来标识事务处理的类,并通过 @Autowired 注解将 CustomerMapper 接口注入到本类中。
    小提示:这里先将@Transactional 注解进行了注释,是为了先执行此类没有事务管理的情况。 之后再删除注释,执行包含事务管理的情况,即可通过结果来验证事务是否配置成功。
    ( 4 )在 Spring 的配置文件中,编写开启注解扫描的配置代码,代码如下所示。

       <!-- 开启扫描  -->
      <context:component-scan base-package="com.neuedu.mapper" /> 
    

    ( 5 )在 com.neuedu.test 包中,创建测试类 TransactionTest,在测试类的 main() 方法中编写测试事务执行的代码,文件如下所示。

    package com.neuedu.test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import com.neuedu.po.Customer;
    import com.neuedu.service.CustomerService;
    /**
    * 测试事务
    */
    public class TransactionTest {
      public static void main(String[] args) {
          ApplicationContext act= new ClassPathXmlApplicationContext("applicationContext.xml");
          CustomerService customerService = act.getBean(CustomerService.class);
          Customer customer = new Customer();
          customer.setUsername("admin");
          customer.setPhone("15140005000");
          customerService.addCustomer(customer);
      }
    }
    

    在文中,首先获取了 CustomerService 的实例,然后创建了 Customer 对象,并向对象中添加属性值,最后调用了实例的 addCustomer() 方法执行添加客户操作。 在运行测试方法之前,先来查看一下数据库中的已有数据,如图所示。



    从图中可以看到,此时数据表中只有 10 条数据。 执行测试类中的 main() 方法后,控制台的输出结果如图所示。



    从图中可以看到,程序已经执行了插入操作,并且在执行到错误代码时抛出了异常信息。 再次查询 t_customer 表,其表中的数据如图所示。

    从图中可以看到,新添加的数据已经存储在了 t_customer 表中,这说明项目中的事务管理没有起作用。 此时将前面文件中@Transactional 前面的注释删除,再次执行测试类中的 main() 方法后,虽然 Eclipse 的控制台也会显示抛出的异常信息,但是此时 t_custömer 表中依然只有 11 条数据,如图所示。




    这也就说明项目中的事务配置是正确的,至此,对于整合时事务功能的测试就已经完成。
    本章小结

    本章首先对 MyBatis 与 Spring 框架整合的环境搭建进行了讲解,然后讲解了使用传统 DAO 方式的开发整合,以及基于 Mapper 接口方式的开发整合。 通过本章的学习,大家能够熟练地掌握 MyBatis 与 Spring 框架的几种整合方式,这将为以后项目的学习打下坚实的基础。

    相关文章

      网友评论

        本文标题:第 10 章 MyBatis 与 Spring 的整合

        本文链接:https://www.haomeiwen.com/subject/quhusctx.html