0%

Spring集成Mybatis3.5

  • Spring集成Mybatis3.5
    • 具体实现
    • Spring 主配置文件引入子配置文件

十八、Spring集成Mybatis3.5

18.1 实现步骤

  • 第一步:准备数据库表。

    • 使用 t_act 表(账户表)。
  • 第二步:IDEA 中创建一个模块 spring6-011-springmybatis ,并引入相关依赖:

    • spring-context
      • 会关联引入 aop 依赖,spring-aop
    • spring-jdbc
      • 会关联引入事务依赖,spring-tx
    • mysql 驱动
    • mybatis
    • mybatis-springmybatis提供的与spring框架集成的依赖
    • 德鲁伊连接池 druid
    • junit
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.f</groupId>
    <artifactId>spring6-011-springmybatis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <!--仓库-->
    <repositories>
    <repository>
    <id>repository.spring.milestone</id>
    <name>Spring Milestone Repository</name>
    <url>https://repo.spring.io/milestone</url>
    </repository>
    </repositories>
    <!--依赖-->
    <dependencies>
    <!--spring context依赖-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.0.8</version>
    </dependency>
    <!--spring jdbc依赖-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>6.0.8</version>
    </dependency>
    <!--mysql驱动依赖-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
    </dependency>
    <!--myabtis依赖-->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.10</version>
    </dependency>
    <!--mybatis-spring依赖-->
    <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>3.0.3</version>
    </dependency>
    <!--druid依赖-->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.20</version>
    </dependency>
    <!--junit依赖-->
    <dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.9.0</version>
    <scope>test</scope>
    </dependency>
    </dependencies>

    <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    </project>
  • 第三步:基于三层架构实现,提前创建好所有的包。

    • com.f.bank.mapper
      • 在 Mybatis 中习惯将 dao 写成 mapper,并且不需要写实现类,因为 Mybatis 会通过动态代理机制自动给我们生成实现类。
    • com.f.bank.service
      • com.f.bank.service.impl
    • com.f.bank.pojo
  • 第四步:编写 pojo 类。

    • Account类,属性私有化,提供公开的 settergettertoString 方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      package com.f.spring6.pojo;

      /**
      * @author fzy
      * @date 2024/1/27 14:58
      */
      public class Account {
      private String actno;
      private Double balance;

      public Account() {
      }

      public Account(String actno, Double balance) {
      this.actno = actno;
      this.balance = balance;
      }

      @Override
      public String toString() {
      return "Account{" +
      "actno='" + actno + '\'' +
      ", balance=" + balance +
      '}';
      }

      public String getActno() {
      return actno;
      }

      public void setActno(String actno) {
      this.actno = actno;
      }

      public Double getBalance() {
      return balance;
      }

      public void setBalance(Double balance) {
      this.balance = balance;
      }
      }
  • 第五步:编写 mapper 接口。

    • AccountMapper 接口,定义方法。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      package com.f.spring6.mapper;

      import com.f.spring6.pojo.Account;

      import java.util.List;

      /**
      * @author fzy
      * @date 2024/1/27 15:00
      */
      public interface AccountMapper { // 该接口的实现类是Mybatis通过动态代理机制动态生成的
      // 新增账户
      int insert(Account account);

      // 根据账号删除账户
      int deleteByActno(String actno);

      // 修改账户
      int update(Account account);

      // 根据账号查询账户
      Account selectByActno(String actno);

      // 查询所有账户
      List<Account> selectAll();
      }
  • 第六步:编写 mapper 配置文件。

    • 在配置文件中配置命名空间为AccountMapper 接口的全类名,以及每一个方法对应的 sql

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      <?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.f.spring6.mapper.AccountMapper">
      <insert id="insert">
      INSERT INTO t_act VALUES (#{actno}, #{balance})
      </insert>
      <delete id="deleteByActno">
      DELETE FROM t_act
      <where>
      actno = #{actno}
      </where>
      </delete>
      <update id="update">
      UPDATE t_act
      <set>
      balance = #{balance}
      </set>
      <where>
      actno = #{actno}
      </where>
      </update>
      <select id="selectByActno" resultType="Account">
      SELECT actno, balance
      FROM t_act
      <where>
      actno = #{actno}
      </where>
      </select>
      <select id="selectAll" resultType="Account">
      SELECT actno, balance
      FROM t_act
      </select>
      </mapper>
  • 第七步:编写 service 接口和 service 接口实现类。

    • AccountService

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      package com.f.spring6.service;

      import com.f.spring6.pojo.Account;

      import java.util.List;

      /**
      * @author fzy
      * @date 2024/1/27 15:14
      */
      public interface AccountService {
      // 开户
      int save(Account account);

      // 销户
      int deleteByActno(String actno);

      // 修改账户
      int modify(Account account);

      // 查询账户
      Account getByActno(String actno);

      // 查询所有账户
      List<Account> getAll();

      // 转账
      void transfer(String fromActno, String toActno, double money);
      }
    • AccountServiceImpl

      • 添加事务 @Transactional
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      package com.f.spring6.service.impl;

      import com.f.spring6.mapper.AccountMapper;
      import com.f.spring6.pojo.Account;
      import com.f.spring6.service.AccountService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      import org.springframework.transaction.annotation.Transactional;

      import java.util.List;

      /**
      * @author fzy
      * @date 2024/1/27 15:17
      */
      @Service("accountService")
      @Transactional
      public class AccountServiceImpl implements AccountService {
      @Autowired
      private AccountMapper accountMapper;

      @Override
      public int save(Account account) {
      return accountMapper.insert(account);
      }

      @Override
      public int deleteByActno(String actno) {
      return accountMapper.deleteByActno(actno);
      }

      @Override
      public int modify(Account account) {
      return accountMapper.update(account);
      }

      @Override
      public Account getByActno(String actno) {
      return accountMapper.selectByActno(actno);
      }

      @Override
      public List<Account> getAll() {
      return accountMapper.selectAll();
      }

      @Override
      public void transfer(String fromActno, String toActno, double money) {
      Account fromAct = accountMapper.selectByActno(fromActno);
      Account toAct = accountMapper.selectByActno(toActno);
      if (fromAct.getBalance() < money) {
      throw new RuntimeException("账户余额不足");
      }
      fromAct.setBalance(fromAct.getBalance() - money);
      toAct.setBalance(toAct.getBalance() + money);
      int count = accountMapper.update(fromAct);
      // 人为设置异常
      //String s = null;
      //s.toString();
      count += accountMapper.update(toAct);
      if (count != 2) {
      throw new RuntimeException("未知异常,转账失败");
      }
      }
      }
  • 第八步:编写 jdbc.properties 配置文件。

    • 数据库连接池相关信息。

      1
      2
      3
      4
      jdbc.driver=com.mysql.cj.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/spring6
      jdbc.username=root
      jdbc.password=root
  • 第九步:编写 mybatis-config.xml 配置文件。

    • 该文件可以没有,大部分的配置可以转移到 Spring 配置文件中。

    • 如果遇到 Mybatis 相关的系统级配置,还是需要这个文件。如:缓存。

      • Spring 集成 Mybatis 之后,可以将 Mybatis 的核心配置文件中的大部分的配置转移到 Spring 配置文件中,所以可以没有 Mybatis 的核心配置文件,如果遇到 Mybatis 相关的系统级配置,还是需要这个文件。所以只要不进行系统级参数的配置, Mybatis 配置文件可以省略。
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <?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>
      <settings>
      <!--帮助我们打印mybatis的日志信息、sql语句等-->
      <setting name="logImpl" value="STDOUT_LOGGING"/>
      </settings>
      </configuration>
  • 第十步:编写 spring.xml 配置文件。

    • 组件扫描
    • 引入外部的属性文件
    • 数据源(德鲁伊连接池)
    • SqlSessionFactoryBean 配置
      • 注入 mybatis 核心配置文件路径
      • 指定别名包
      • 注入数据源
    • Mapper 扫描配置器
      • 主要扫描 Mapper 接口,生成代理类
    • 事务管理器 DataSourceTransactionManager
      • 注入数据源
    • 启用事务注解
      • 注入事务管理器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--组件扫描-->
    <context:component-scan base-package="com.f.spring6"/>
    <!--引入外部属性配置文件-->
    <context:property-placeholder location="jdbc.properties"/>
    <!--数据源(德鲁伊连接池)-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--配置SqlSessionFactoryBean-->
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--注入数据源-->
    <property name="dataSource" ref="dataSource"/>
    <!--指定mybatis核心配置文件-->
    <property name="configLocation" value="mybatis-config.xml"/>
    <!--指定别名包-->
    <property name="typeAliasesPackage" value="com.f.spring6.pojo"/>
    </bean>
    <!--配置Mapper扫描配置器,主要扫描Mapper接口,生成代理类-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.f.spring6.mapper"/>
    </bean>
    <!--配置事务管理器-->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--启用事务注解-->
    <tx:annotation-driven transaction-manager="txManager"/>
    </beans>
  • 第十一步:编写测试程序,进行测试。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.f.spring6.test;

    import com.f.spring6.service.AccountService;
    import org.junit.jupiter.api.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;

    /**
    * @author fzy
    * @date 2024/1/27 15:44
    */
    public class SpringMybatisTest {
    @Test
    public void testSpringMybatis() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
    try {
    accountService.transfer("act001", "act002", 10000.0);
    System.out.println("转账成功");
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

18.2 Spring 主配置文件引入子配置文件

  • Spring 配置文件可以有多个,并且可以在 Spring 的核心配置文件中使用 import 引入子配置文件。

    • 例如我们可以将组件扫描单独定义到一个配置文件中。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
      <!--组件扫描-->
      <context:component-scan base-package="com.f.spring6"/>
      </beans>

      然后在核心配置文件中使用 import 标签引入子配置文件:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xmlns:tx="http://www.springframework.org/schema/tx"
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
      <!--在spring的核心配置文件中引入组件扫描子配置文件-->
      <import resource="spring-common.xml"/>
      ......
      </beans>
  • 在实际开发中,配置可能会很多,service 单独配置到一个文件中,dao 单独配置到一个文件中,然后在核心配置文件中引入,养成好习惯。

---------------The End---------------