🎉在工作场景中遇到这样一个需求,对表中的数据进行更新,更新的步骤是:首先,删除表中所有的数据记录;之后,再将更新过后的数据插入到表中。由于系统业务逻辑相关的原因,在数据插入时可能会出现异常,因此当出现异常而终止插入过程,需要能够将事务进行回滚,恢复之前删除的数据。
?这里肯定是需要使用事务进行控制了,那么在使用 Spring 框架提供的声明式事务注解方式@Transactional ,并确认避免了事务失效的几种情况之后,在测试接口时事务还是没有生效。
?以下是主要的相关方法实现:
@Transactional(rollbackFor = Exception.class)
public void runDeptTask() {
try {
deptMapper.deleteAll();
} catch (Exception e) {
e.printstack();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
?在确认 Java 代码层面并没有问题之后,便开始从数据库层面开始排查问题。首先,检查是否使用了支持事务的存储引擎,确认 MySQL 数据库使用了 InnoDB 引擎并开启了事务机制。之后,在检查 SQL 语句时发现,删除数据时的语法使用了 truncate ,而不是使用 delete 语法。
?这时便回忆起,为了保证事务的原子性,InnoDB 引擎在实际进行记录的增删改操作时,都需要先把 undo 日志记下来,便于之后进行回滚。这里的增删改对应的语法是:insert 、delete 、update ,没有对使用 truncate 删除的 undo 日志。这便是发生问题的所在之处了,因此需要将删除时使用的语法改为 delete ,这样才能使得事务回滚起效,问题得到解决。
?更改过后的 SQL 语句如下:
DeptMapper.xml
<delete id = "deleteAll">
delete from sys_dept
</delete>
|