本项目为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;
dept_inf表中当前数据为
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";
}
}
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;
}
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("抛出自定义异常");
}
}
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);
}
说明:因为表dept_inf中没有字段 NAME1, REMARK1,所以,在调用方法void insertTrans(DeptInfo deptInfo)会抛出异常。
代码
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);
}
}
预期:
尽管
deptInfoMapper.insertTrans(deptInfo);
该行会抛出异常,但是由于没有加@Transactional,就没有事务控制。
所以,下面这行会正常插入
deptInfoMapper.insert(deptInfo1);
验证
抛出了异常就,但是数据库仍然插入了数据。
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);
}
}
预期
该行插入数据后,
deptInfoMapper.insert(deptInfo1);
由于
deptInfoMapper.insertTrans(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);
// 抛出自定义异常继承自Exception
throw new CustomException("抛出自定义异常");
}
}
注意:自定义异常继承自Exception
预期
未知
验证
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("抛出自定义异常");
}
}
验证
附:java异常分类