SSM整合(五)

SSM整合之事务管理(一)

1.核心准备工作

1.1 导入spring-tx依赖

<!-- 事务spring-tx -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.22</version>
</dependency>

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.3 创建spring-tx.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: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">
     <!--创建事务管理器 通过Jdbc方式-->
     <bean id="tm" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="dataSource"></property>
     </bean>
    <!--开启注解事务 选tx结尾的 报错后就回滚-->
    <tx:annotation-driven transaction-manager="tm"></tx:annotation-driven>
</beans>

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);
}

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;
    }
}

4 写员工业务接口EmpService

package com.service;

import com.entity.Emp;
//接口继承借口,类继承类
public interface EmpService extends BaseService<Emp>{
    //属于员工转账业务
    void transfer(int account1, int account2, int money);
}

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 {
}

6 事务管理

6.1 理由

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

6.2 如何用

6.2.1 逻辑错误
a 出现原因
当你查询不到任何结果时,返回的是null,对一个为null值的对象调用方法,必然会出现空指针异常
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);
    }
b.2 测试代码
 @Test
    public void t99(){
        //需要保证一致性
       es.zz(99980,7499,100);
    }
b.3 运行截图

在这里插入图片描述

b.4 解决方案(执行后面逻辑前加判断)
if(emp1==null) throw new RuntimeException(account1+"账号不存在");
if(emp2==null) throw new RuntimeException(account2+"账号不存在");
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);
    }
b.2 测试方法
@Test
    public void t(){
       es.transfer(7369,7499,100);
    }
b.3 运行前的数据表截图

在这里插入图片描述

b.4 运行截图

在这里插入图片描述

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

在这里插入图片描述

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SSS4362

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值