这里就不对事务进行详细的介绍。
事务的特性ACID,原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
因项目需要同时对两个表进行操作,其中一个操作出现问题时,则回退至操作没有发生的时候。
举例:
a表保存个人信息,个人的部门信息保存在b表中,b表有一个字段与a表主键进行关联
(这样设计并不符合规范,为了方便就这么解释了--应当在新建一个表c 与a和b做关系映射)
现在需要将a表中的人删除,则相应的应该将b表中与被删除的人所关联的记录全部删除
两种解决方案:
1、 调用两次mapper 采用springboot提供的@Transactional注解
使用注解时,第一次进行测试 发现empInfoMapper.delete(id)
顺利执行在orgEmpMapper.deleteEmp(id)
创造一个异常发现人员表中数据成功删除,组织表中数据还存在。
经过排查发现是因为在service中进行了异常的捕获,@Transactional在捕获异常时会进行回滚,我在代码中已经进行了异常的捕获,@Transactional不能捕获异常无法进行回滚。
异常代码
在service中进行了异常捕获,将try...catch 放到controller中进行处理
@Override
@Transactional(rollbackFor = Exception.class)
public int delete(Long id) {
try{
//删除人员表中数据
int delete= empInfoMapper.delete(id);
//删除组织表中数据
int deleteOrg= orgEmpMapper.delete(id);
if (delete== 1 && deleteOrg== 1) {
return 1;
}
}catch(Exception e){
logger.error(e);
e.printStackTrace();
}
return 0;
}
正确的处理:
controller代码
@DeleteMapping()
public Response<Integer> delete(@RequestParam(value = "id", required = false) Long id) {
if (null == id|| null == id) {
return new Response<>(OutPutCode.FAILED_WRONG_PARAM, null);
}
try {
int delete= iSysOrgEmpService.delete(orgId, orgLid, empInfo);
if (insert == 0) {
return new Response<>(OutPutCode.FAILED, null);
}
return new Response<>(OutPutCode.SUCCESS, insert);
} catch (Exception e) {
logger.error(e);
e.printStackTrace();
}
return new Response<>(OutPutCode.FAILED, null);
}
`service代码`
@Override
@Transactional(rollbackFor = Exception.class)
public int delete(Long id) {
//删除人员表中数据
int delete= empInfoMapper.delete(id);
//删除组织表中数据
int deleteOrg= orgEmpMapper.delete(id);
if (delete== 1 && deleteOrg== 1) {
return 1;
}
return 0;
}
2、利用Sql的事务回滚进行处理
BEGIN; #开启事务
delete #人员表表中删除
from emp_info
where id = xxx;
delete #组织表中删除关联记录
from org_emp
where emp_id = xxx;
ROLLBACK; #事务回滚至开启事务的节点