• org.springframework.transaction.annotation.Transactional 简单使用示例


    测试项目环境

    本项目为springboot项目,ORM框架为mybatis,数据库为MySQL8

    数据库

    DDL

    CREATE TABLE `dept_inf` (
      `ID` int(11) NOT NULL AUTO_INCREMENT,
      `NAME` varchar(50) NOT NULL,
      `REMARK` varchar(300) DEFAULT NULL,
      `NUM` int(11) DEFAULT '0',
      PRIMARY KEY (`ID`)
    ) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    dept_inf表中当前数据为
    在这里插入图片描述

    java源码

    controller

    package com.xl.test.springbootaop.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.xl.test.springbootaop.service.DeptInfoService;
    
    @RestController
    @RequestMapping("/transaction")
    public class TransactionTestController {
    	
    	@Autowired
    	DeptInfoService deptInfoService;
    	
    	@RequestMapping("/roll")
    	public String transactionTest() {
    		try {
    			deptInfoService.insertTrans();
    		} catch (Exception e) {
    			return "抛出了异常:"+e.getMessage();
    		}
    		return "bbb";
    	}
    }
    
    
    • 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

    Service

    package com.xl.test.springbootaop.service;
    
    import com.xl.test.springbootaop.entity.DeptInfo;
    import com.xl.test.springbootaop.util.CustomException;
    
    public interface DeptInfoService {
    	
    	/**
    	 *  	插入部门信息
    	 * @param deptInfo 待插入的部门信息
    	 */
    	void insert(DeptInfo deptInfo);
    
    	void insertTrans() throws CustomException;
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    ServiceImpl

    package com.xl.test.springbootaop.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.xl.test.springbootaop.dao.DeptInfoMapper;
    import com.xl.test.springbootaop.entity.DeptInfo;
    import com.xl.test.springbootaop.service.DeptInfoService;
    import com.xl.test.springbootaop.util.CustomException;
    
    @Service
    //@Transactional
    public class DeptInfoServiceImpl implements DeptInfoService {
    	
    	@Autowired
    	DeptInfoMapper deptInfoMapper;
    	
    	public void insert(DeptInfo deptInfo) {
    		if (deptInfo == null) {
    			deptInfo = new DeptInfo();
    			deptInfo.setNAME("测试001");
    			deptInfo.setREMARK("这是测试001");
    		}
    		deptInfoMapper.insert(deptInfo);
    	}
    
    	public void insertTrans() throws CustomException {
    		DeptInfo deptInfo1 = new DeptInfo();
    		deptInfo1.setNAME("事务测试");
    		deptInfo1.setREMARK("事务测试");
    		//正常插入, rollback
    		deptInfoMapper.insert(deptInfo1);
    		
    		DeptInfo deptInfo = new DeptInfo();
    		deptInfo.setNAME("as");
    		deptInfo.setREMARK("rm");
    //		try {
    			// throws RunTimeException
    //			deptInfoMapper.insertTrans(deptInfo);
    //		} catch (Exception e) {
    			// do nothing...
    //		}
    		
    		// 抛出自定义异常继承自Exception
    	   // throw new CustomException("抛出自定义异常");
    		
    	}
    
    }
    
    
    • 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

    mybatis mapper

    package com.xl.test.springbootaop.dao;
    
    import org.apache.ibatis.annotations.Insert;
    
    import com.xl.test.springbootaop.entity.DeptInfo;
    
    public interface DeptInfoMapper {
    	
    	@Insert("INSERT INTO dept_inf(NAME,REMARK) VALUES(#{NAME},#{REMARK})")
    	void insert(DeptInfo deptInfo);
    	
    	@Insert("INSERT INTO dept_inf(NAME1,REMARK1) VALUES(#{NAME},#{REMARK})")
    	void insertTrans(DeptInfo deptInfo);
    	
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    说明:因为表dept_inf中没有字段 NAME1, REMARK1,所以,在调用方法void insertTrans(DeptInfo deptInfo)会抛出异常。

    测试项目

    测试一: 在业务实现层,不加@Transactional

    代码

    package com.xl.test.springbootaop.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.xl.test.springbootaop.dao.DeptInfoMapper;
    import com.xl.test.springbootaop.entity.DeptInfo;
    import com.xl.test.springbootaop.service.DeptInfoService;
    import com.xl.test.springbootaop.util.CustomException;
    
    @Service
    //@Transactional
    public class DeptInfoServiceImpl implements DeptInfoService {
    	
    	@Autowired
    	DeptInfoMapper deptInfoMapper;
    	
    	public void insert(DeptInfo deptInfo) {
    		if (deptInfo == null) {
    			deptInfo = new DeptInfo();
    			deptInfo.setNAME("测试001");
    			deptInfo.setREMARK("这是测试001");
    		}
    		deptInfoMapper.insert(deptInfo);
    	}
    
    	public void insertTrans() throws CustomException {
    		DeptInfo deptInfo1 = new DeptInfo();
    		deptInfo1.setNAME("事务测试");
    		deptInfo1.setREMARK("事务测试");
    		//正常插入, rollback
    		deptInfoMapper.insert(deptInfo1);
    		
    		DeptInfo deptInfo = new DeptInfo();
    		deptInfo.setNAME("as");
    		deptInfo.setREMARK("rm");
    	    deptInfoMapper.insertTrans(deptInfo);
    
    	}
    
    }
    
    
    • 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

    预期:
    尽管

    deptInfoMapper.insertTrans(deptInfo);
    
    • 1

    该行会抛出异常,但是由于没有加@Transactional,就没有事务控制。

    所以,下面这行会正常插入

    deptInfoMapper.insert(deptInfo1);
    
    • 1

    验证
    在这里插入图片描述
    在这里插入图片描述
    抛出了异常就,但是数据库仍然插入了数据。

    测试二: 在业务层加上@Transactional

    package com.xl.test.springbootaop.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.xl.test.springbootaop.dao.DeptInfoMapper;
    import com.xl.test.springbootaop.entity.DeptInfo;
    import com.xl.test.springbootaop.service.DeptInfoService;
    import com.xl.test.springbootaop.util.CustomException;
    
    @Service
    @Transactional
    public class DeptInfoServiceImpl implements DeptInfoService {
    	
    	@Autowired
    	DeptInfoMapper deptInfoMapper;
    	
    	public void insert(DeptInfo deptInfo) {
    		if (deptInfo == null) {
    			deptInfo = new DeptInfo();
    			deptInfo.setNAME("测试001");
    			deptInfo.setREMARK("这是测试001");
    		}
    		deptInfoMapper.insert(deptInfo);
    	}
    
    	public void insertTrans() throws CustomException {
    		DeptInfo deptInfo1 = new DeptInfo();
    		deptInfo1.setNAME("事务测试");
    		deptInfo1.setREMARK("事务测试");
    		//正常插入, rollback
    		deptInfoMapper.insert(deptInfo1);
    		
    		DeptInfo deptInfo = new DeptInfo();
    		deptInfo.setNAME("as");
    		deptInfo.setREMARK("rm");
    	    deptInfoMapper.insertTrans(deptInfo);
    
    	}
    
    }
    
    • 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

    预期

    该行插入数据后,

    deptInfoMapper.insert(deptInfo1);
    
    • 1

    由于

    deptInfoMapper.insertTrans(deptInfo);
    
    • 1

    会抛出异常,加上@Transactional事务控制原因,事务会回滚,数据库最终不会有数据。

    验证
    在这里插入图片描述
    在这里插入图片描述

    测试三: 抛出自定义异常

    package com.xl.test.springbootaop.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.xl.test.springbootaop.dao.DeptInfoMapper;
    import com.xl.test.springbootaop.entity.DeptInfo;
    import com.xl.test.springbootaop.service.DeptInfoService;
    import com.xl.test.springbootaop.util.CustomException;
    
    @Service
    @Transactional
    public class DeptInfoServiceImpl implements DeptInfoService {
    	
    	@Autowired
    	DeptInfoMapper deptInfoMapper;
    	
    	public void insert(DeptInfo deptInfo) {
    		if (deptInfo == null) {
    			deptInfo = new DeptInfo();
    			deptInfo.setNAME("测试001");
    			deptInfo.setREMARK("这是测试001");
    		}
    		deptInfoMapper.insert(deptInfo);
    	}
    
    	public void insertTrans() throws CustomException {
    		DeptInfo deptInfo1 = new DeptInfo();
    		deptInfo1.setNAME("事务测试");
    		deptInfo1.setREMARK("事务测试");
    		//正常插入, rollback
    		deptInfoMapper.insert(deptInfo1);
    				
    		// 抛出自定义异常继承自Exception
    	    throw new CustomException("抛出自定义异常");
    		
    	}
    
    }
    
    • 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

    注意:自定义异常继承自Exception

    预期
    未知

    验证
    在这里插入图片描述
    在这里插入图片描述

    测试四:仍然抛出自定义异常,但是,@Transactional后面加上(rollbackFor = Exception.class)

    package com.xl.test.springbootaop.service.impl;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.xl.test.springbootaop.dao.DeptInfoMapper;
    import com.xl.test.springbootaop.entity.DeptInfo;
    import com.xl.test.springbootaop.service.DeptInfoService;
    import com.xl.test.springbootaop.util.CustomException;
    
    @Service
    @Transactional(rollbackFor = Exception.class)
    public class DeptInfoServiceImpl implements DeptInfoService {
    	
    	@Autowired
    	DeptInfoMapper deptInfoMapper;
    	
    	public void insert(DeptInfo deptInfo) {
    		if (deptInfo == null) {
    			deptInfo = new DeptInfo();
    			deptInfo.setNAME("测试001");
    			deptInfo.setREMARK("这是测试001");
    		}
    		deptInfoMapper.insert(deptInfo);
    	}
    
    	public void insertTrans() throws CustomException {
    		DeptInfo deptInfo1 = new DeptInfo();
    		deptInfo1.setNAME("事务测试");
    		deptInfo1.setREMARK("事务测试");
    		//正常插入, rollback
    		deptInfoMapper.insert(deptInfo1);
    				
    		// 抛出自定义异常继承自Exception
    	    throw new CustomException("抛出自定义异常");
    		
    	}
    
    }
    
    • 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

    验证
    在这里插入图片描述

    @Transactional官方解释

    在这里插入图片描述

    在这里插入图片描述

    部分翻译

    在这里插入图片描述
    在这里插入图片描述

    附:java异常分类
    在这里插入图片描述

  • 相关阅读:
    scratch芝麻开门 2023年9月中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析
    红队专题-新型webshell的研究
    Openfoam UPstream类探索(一)
    【MATLAB源码-第42期】基于matlab的人民币面额识别系统(GUI)。
    Linux·字符设备和杂项设备
    【C++】从文件获取json信息
    K8s小白?应用部署太难?看这篇就够了!
    cmake简略使用介绍
    嵌入式项目_嵌入式Linux项目分享_linux系统编程
    基于JAVA+SpringBoot+Vue+协同过滤算法+爬虫的前后端分离的租房系统
  • 原文地址:https://blog.csdn.net/qq_29025955/article/details/126261709