• (十八)Spring6集成MyBatis3.5



    Spring学习目录

    上一篇:(十七)Spring6整合JUnit

    下一篇:(十九)Spring中的八大模式

    实现步骤

    功能是账户转账:

    • 第一步:准备数据库表
      使用t_act表(账户表)
    • 第二步:IDEA中创建一个Maven模块,并引入依赖
      spring-context、spring-jdbc、mysql驱动、mybatis、mybatis-spring:mybatis提供的与spring框架集成的依赖、德鲁伊连接池、junit
    • 第三步:基于三层架构实现,所以提前创建好所有的包
      mapper、service、service.impl、pojo
    • 第四步:编写pojo
      Account,属性私有化,提供公开的setter getter和toString。
    • 第五步:编写mapper接口
      AccountMapper接口,定义方法
    • 第六步:编写mapper配置文件
      在配置文件中配置命名空间,以及每一个方法对应的sql。
    • 第七步:编写service接口和service接口实现类
      AccountService、AccountServiceImpl
    • 第八步:编写jdbc.properties配置文件
      数据库连接池相关信息
    • 第九步:编写mybatis-config.xml配置文件
      该文件可以没有,大部分的配置可以转移到spring配置文件中。
      如果遇到mybatis相关的系统级配置,还是需要这个文件。
      第十步:编写spring.xml配置文件
      组件扫描、引入外部的属性文件、数据源
      SqlSessionFactoryBean配置:
      • 注入mybatis核心配置文件路径
      • 指定别名包
      • 注入数据源

    Mapper扫描配置器:指定扫描的包
    事务管理器DataSourceTransactionManager:注入数据源
    启用事务注解:注入事务管理器

    • 第十一步:编写测试程序,并添加事务,进行测试

    具体实现

    第一步:准备数据库表

    表结构:
    请添加图片描述
    初始数据:
    请添加图片描述

    第二步:IDEA中创建一个模块,并引入依赖

    依赖:

    <!--配置多个仓库-->
      <repositories>
        <!--spring6里程碑版本的仓库-->
        <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.0-M2</version>
        </dependency>
        <!--spring jdbc-->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>6.0.0-M2</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.30</version>
        </dependency>
        <!--Mybatis-->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.5.10</version>
        </dependency>
        <!--Myvatis-spring-->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
          <version>2.0.7</version>
        </dependency>
        <!--德鲁伊连接池-->
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.14</version>
        </dependency>
        <!--junit-->
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.13.2</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
    • 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

    第三步:基于三层架构实现,所以提前创建好所有的包

    在这里插入图片描述

    第四步:编写pojo

    /**
     * 简单的账户类
     */
    public class Account {
        private Long id;
        private String actno;
        private Double balance;
    
        public Account() {
        }
    
        public Account(Long id, String actno, Double balance) {
            this.id = id;
            this.actno = actno;
            this.balance = balance;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", actno='" + actno + '\'' +
                    ", balance=" + balance +
                    '}';
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        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;
        }
    }
    
    
    • 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

    第五步:编写mapper接口

    public interface AccountMapper {
    
        /**
         * 保存账户
         * @param account
         * @return
         */
        int insert(Account account);
    
        /**
         * 根据账号删除账户
         * @param actno
         * @return
         */
        int deleteByActno(String actno);
    
        /**
         * 修改账户
         * @param account
         * @return
         */
        int update(Account account);
    
        /**
         * 根据账号查询账户
         * @param actno
         * @return
         */
        Account selectByActno(String actno);
    
        /**
         * 获取所有账户
         * @return
         */
        List<Account> selectAll();
    }
    
    
    • 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

    第六步:编写mapper配置文件

    一定要注意,创建这个目录。注意是斜杠不是点。在resources目录下新建。并且要和Mapper接口包对应上。
    请添加图片描述
    接口叫做AccountMapper,配置文件必须是AccountMapper.xml

    <?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.bank.mapper.AccountMapper">
        <insert id="insert">
            insert into 
                t_act
            values(null,#{actno},#{balance})
        </insert>
    
        <delete id="deleteById">
            delete from
                t_act
            where
                actno = #{actno}
        </delete>
    
        <update id="update">
            update 
                t_act
            set 
                balance = #{balance}
            where
                actno = #{actno}
        </update>
    
        <select id="selectByActno" resultType="Account">
            select
                *
            from
                t_act
            where
                actno = #{actno}
        </select>
    
        <select id="selectAll" resultType="account">
            select
                *
            from
                t_act
        </select>
    </mapper>
    
    • 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

    第七步:编写service接口和service接口实现类

    注意编写的service实现类纳入IoC容器管理:
    AccountService接口:

    public interface AccountService {
        /**
         * 开户
         * @param act
         * @return
         */
        int save(Account act);
    
        /**
         * 根据账号销户
         * @param actno
         * @return
         */
        int deleteByActno(String actno);
    
        /**
         * 修改账户
         * @param act
         * @return
         */
        int update(Account act);
    
        /**
         * 根据账号获取账户
         * @param actno
         * @return
         */
        Account getByActno(String actno);
    
        /**
         * 获取所有账户
         * @return
         */
        List<Account> getAll();
    
        /**
         * 转账
         * @param fromActno
         * @param toActno
         * @param money
         */
        void transfer(String fromActno, String toActno, double money);
    }
    
    
    • 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

    AccountService接口实现类:

    @Transactional
    @Service("accountService")
    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.deleteById(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 moeny) {
            Account fromAct = accountMapper.selectByActno(fromActno);
            if (fromAct.getBalance() < moeny) {
                throw new RuntimeException("余额不足");
            }
            Account toAct = accountMapper.selectByActno(toActno);
            fromAct.setBalance(fromAct.getBalance() - moeny);
            toAct.setBalance(toAct.getBalance() + moeny);
    
            int count = accountMapper.update(fromAct);
    
            //模拟异常
            /*String s = null;
            s.toString();*/
    
            count += accountMapper.update(toAct);
    
            if (count != 2) {
                throw new RuntimeException("转账失败");
            }
    
        }
    }
    
    • 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

    第八步:编写jdbc.properties配置文件

    jdbc.properties放在类的根路径下:

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mvc
    jdbc.username=root
    jdbc.password=root
    
    • 1
    • 2
    • 3
    • 4

    第九步:编写mybatis-config.xml配置文件

    放在类的根路径下,有些系统级配置spring配置文件没办法完成,可以在mybatis核心配置文件配置,例如懒加载等。
    这里只开启日志,其他配置到spring.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>
        <!--帮助我们打印mybatis的日志信息。sql语句等-->
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
    </configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    第十步:编写spring.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"
           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.bank"/>
    
        <!--
            引入外部属性配置文件
            之前说过Spring默认加载的是电脑的系统环境,在context:property-placeholder可以使用system-properties-mode属性关闭。
            系统属性模式,默认ENVIRONMENT(表示先找ENVIRONMENT,再找properties-ref/location的),
            NEVER:表示永远不用ENVIRONMENT的,
            OVERRIDE类似于ENVIRONMENT
        -->
        <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
        <!--配置数据源  init连接开始使用应该初始化,close连接使用完应该关闭-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" 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}"/>
        </bean>
        <!--配置SqlSessionFactoryBean-->
        <bean class="org.mybatis.spring.SqlSessionFactoryBean">
            <!--注入数据源-->
            <property name="dataSource" ref="dataSource"/>
            <!--核心配置文件-->
            <property name="configLocation" value="mybatis-config.xml"/>
            <!--指定别名-->
            <property name="typeAliasesPackage" value="com.bank.pojo"/>
        </bean>
        <!--配置Mapper扫描配置器-->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!--指定要扫描的包名-->
            <property name="basePackage" value="com.bank.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
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    第十一步:编写测试程序,并添加事务,进行测试

    public class Spring_Mybatis_Test {
        @Test
        public void testSM(){
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
            AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
            try {
                accountService.transfer("act001","act002",1000);
                System.out.println("转账成功");
            }catch (Exception e){
                e.printStackTrace();
            }
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行测试程序:
    请添加图片描述
    数据库数据:转账成功
    请添加图片描述

    测试事务,在service的接口实现类的转账方法松开模拟异常代码,再次运行:
    请添加图片描述
    虽然出现异常,但是数据库数据不变,事务控制成功:
    请添加图片描述

    Spring配置文件的import

    在实际开发当中,spring配置文件有多个,并且可以在spring的核心配置文件中使用import进行引入,我们可以将组件扫描单独定义到一个配置文件中,如下:
    spring2.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"
           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.bank"/>
    </beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后在核心配置文件中引入:
    spring.xml:

        <!--组件扫描-->
        <!--<context:component-scan base-package="com.bank"/>-->
    
        <!--Spring核心配置文件中引入其他子spring配置文件-->
        <import resource="spring2.xml"/>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    把模拟异常注释,运行测试程序:
    请添加图片描述
    数据库数据:
    请添加图片描述

  • 相关阅读:
    R语言——taxize(第四部分)
    轻松连接:简化编程中的连接操作
    Linux-安装MySQL(详细教程)
    Pytest自动化测试框架之Allure报告详解
    基于python下django框架 实现校园运动场地预约系统详细设计
    markdown希腊字母
    【从零开始学习 SystemVerilog】3.4、SystemVerilog 控制流—— case( ‘unique‘ 和 ‘priority‘)
    提高采购效率,采购管理的五大原则及实现方法
    数字后端——DEF文件格式
    弹窗里面画echarts图 el-popover
  • 原文地址:https://blog.csdn.net/weixin_45832694/article/details/128080843