• SSM整合(五)


    SSM整合之事务管理(一)

    1.核心准备工作

    1.1 导入spring-tx依赖

    
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-txartifactId>
        <version>5.3.22version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.2 创建实体类

    package com.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import tk.mybatis.mapper.annotation.KeySql;
    
    import javax.persistence.Id;
    import java.io.Serializable;
    
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    //属性必须是引用数据类型 数据库Null值 动态sql都是判断属性是否为空
    public class Emp{
        @Id
        //导入的是javax.persistence下的
        @KeySql(useGeneratedKeys = true)//主键回填
        private Integer empno;
        private String ename;
        private String mgr;
        private String job;
        private String hiredate;
        private Double sal;
        private Double comm;
        private Integer deptno;
    }
    
    • 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

    1.3 创建spring-tx.xml

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
         
         <bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
             <property name="dataSource" ref="dataSource">property>
         bean>
        
        <tx:annotation-driven transaction-manager="tm">tx:annotation-driven>
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2 创建通用业务 BaseService(给实现子类提供方法)

    package com.service;
    
    import java.io.Serializable;
    import java.util.List;
    
    public interface BaseService<T> {
        //mapper是单表的增删改查,impl业务实现层
        List<T> findAll();
        List<T> findAll(T t);
        //实现序列化的类都可以传 number类 String
        T findById(Serializable id);
        T findById(T t);
        boolean insert(T t);
        boolean delete(Serializable id);
        boolean update(T t);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3 创建通用业务实现子类BaseServiceImpl

    package com.service.impl;
    
    import com.service.BaseService;
    import org.springframework.beans.factory.annotation.Autowired;
    import tk.mybatis.mapper.common.Mapper;
    
    import java.io.Serializable;
    import java.util.List;
    
    //该类仅为子类提供公共的增删改查业务方法
    public  abstract class BaseServiceImpl<T> implements BaseService<T> {
        //浏览器-->控制器->业务层-->数据访问层(调用关系)
        //必须要有mapper接口,无就会注入失败
        @Autowired
        Mapper<T> mapper;
        @Override
        public List<T> findAll() {
            return mapper.selectAll();
        }
    
        @Override
        public List<T> findAll(T t) {
            return mapper.select(t);
        }
    
        @Override
        public T findById(Serializable id) {
            return mapper.selectByPrimaryKey(id);
        }
    
        @Override
        public T findById(T t) {
            //查询单个对象
            return mapper.selectOne(t);
        }
    
        @Override
        public boolean insert(T t) {
            //受影响行数
            return mapper.insertSelective(t)>0;
        }
    
        @Override
        public boolean delete(Serializable id) {
            return mapper.deleteByPrimaryKey(id)>0;
        }
    
        @Override
        public boolean update(T t) {
            return mapper.updateByPrimaryKeySelective(t)>0;
        }
    }
    
    • 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

    4 写员工业务接口EmpService

    package com.service;
    
    import com.entity.Emp;
    //接口继承借口,类继承类
    public interface EmpService extends BaseService<Emp>{
        //属于员工转账业务
        void transfer(int account1, int account2, int money);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5 创建员工业务的实现类EmpServiceImpl

    package com.service.impl;
    import com.entity.Emp;
    import com.service.BaseService;
    import com.service.EmpService;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.transaction.interceptor.TransactionAspectSupport;
    @Service
    public class EmpServiceImpl extends BaseServiceImpl<Emp> implements EmpService {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6 事务管理

    6.1 理由

    因为mysql数据库默认是自动提交事务的,程序出现错误并不会自动回滚
    而在一个事务中,当程序发生错误的时候,我们希望回滚到最初的状态,
    所以就需要进行事务管理
    
    • 1
    • 2
    • 3

    6.2 如何用

    6.2.1 逻辑错误
    a 出现原因
    当你查询不到任何结果时,返回的是null,对一个为null值的对象调用方法,必然会出现空指针异常
    
    • 1
    b 错误示例代码
    b.1 转账方法
    @Override
        public void transfer(int account1, int account2, int money) {
                Emp emp1 = findById(account1);
                Emp emp2 = findById(account2);
                //转账
                emp1.setSal(emp1.getSal()-money);
                emp2.setSal(emp2.getSal()+money);
                //修改数据库
                mapper.updateByPrimaryKeySelective(emp1);
                mapper.updateByPrimaryKeySelective(emp2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    b.2 测试代码
     @Test
        public void t99(){
            //需要保证一致性
           es.zz(99980,7499,100);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    b.3 运行截图

    在这里插入图片描述

    b.4 解决方案(执行后面逻辑前加判断)
    if(emp1==null) throw new RuntimeException(account1+"账号不存在");
    if(emp2==null) throw new RuntimeException(account2+"账号不存在");
    
    • 1
    • 2
    6.2.2 运行时错误
    a 解决方案

    在类上面加上@Transactional注解
    在这里插入图片描述

    b 示例代码
    b.1 转账方法
     @Override
        public void transfer(int account1, int account2, int money) {
                Emp emp1 = findById(account1);
                Emp emp2 = findById(account2);
               if(emp1==null) throw new RuntimeException(account1+"账号不存在");
               if(emp2==null) throw new RuntimeException(account2+"账号不存在");
                //转账
                emp1.setSal(emp1.getSal()-money);
                emp2.setSal(emp2.getSal()+money);
                //修改数据库
                mapper.updateByPrimaryKeySelective(emp1);
                System.out.println(1/0);
                mapper.updateByPrimaryKeySelective(emp2);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    b.2 测试方法
    @Test
        public void t(){
           es.transfer(7369,7499,100);
        }
    
    • 1
    • 2
    • 3
    • 4
    b.3 运行前的数据表截图

    在这里插入图片描述

    b.4 运行截图

    在这里插入图片描述

    b.5 运行后的数据表截图

    在这里插入图片描述

  • 相关阅读:
    android 11.0 获取当前界面的APP ,在APP的界面禁止灭屏
    JDBC中的Connection的sql语句
    mqtt综合实战(中国移动OneNET+ESP8266 AT指令)
    CSS实现竖向步骤条
    2019年数维杯数学建模A题 我国省际生态环境与经济交互状况的综合评价求解全过程文档及程序
    Windows下安装与配置Docker
    继承语法详解
    Nginx重写功能
    Go开发工具GoLand V2022.2 来了——Go 工作区重大升级
    s27.linux运维面试题分享
  • 原文地址:https://blog.csdn.net/SSS4362/article/details/127979663