Spring事务回滚机制如何实现

Spring事务回滚机制如何实现

一、Spring事务的概念及特性

1、事务是什么

事务是由一组操作(对数据库数据的处理,例如增、删、改等操作)组成的逻辑单元,要么全部执行成功,要么全部执行失败进行回滚。

2、事务的基本特性

(1)原子性:是一个不可分割的整体;

(2)一致性:事务执行完后,数据的一致性状态要么不变,要么转移到另外一个一致性状态;

(3)隔离性:并发事务之间是独立的;

(4)持久性:对数据的更改永久保存;

二、spring事务的管理、传播方式

1、管理方式

(1)编程式:调用beginTransaction()、commit()、rollback()等事务管理相关的方法

(2)声明式:通过注解或 XML 配置控制事务,推荐使用。

2、传播方式

(1)REQUIRED(默认):默认事务传播行为,存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。

(2)REQUIRE_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。

(3)NESTED:如果当前存在事务,就嵌套当前事务中去执行,如果当前没有事务,那么就新建一个事务,类似 REQUIRE_NEW这个样一个传播行为。

(4)SUPPORTS:表示支持当前当前的事务,如果当前不存在事务,就以非事务的方式去执行。

(5)NOT_SUPPORT: 总是非事务地执行,并挂起任何存在的事务。

(6)MANDATORY:如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。

(7)NEVER:就是以非事务的方式来执行,如果存在事务则抛出一个异常

三、Spring事务的回滚机制

1、事务回滚触发条件

Spring事务的回滚主要基于异常的抛出:

(1)默认情况:

捕获 unchecked Exception(如RuntimeException )或 Error 会导致事务回滚。捕获 Checked Exception(如 IOException)不会回滚,除非明确配置。(2)可指定何种异常回滚

使用 @Transactional(rollbackFor = Exception.class) 明确指定需要回滚的异常。2、事务回滚实现流程

Spring 事务的回滚过程涉及以下关键步骤:

(1)Spring 扫描创建代理对象管理事务,即事务管理器。

(2)方法执行时,事务管理器开启事务。

(3)如果方法抛出指定异常,事务管理器调用数据库的回滚操作。

(4)如果方法成功执行,事务管理器提交事务。

四、Spring事务回滚示例

1、声明式事务回滚示例

(1)默认情况下回滚:

@Service

public class UserServiceImpl extends ServiceImpl implements IUserService {

@Autowired

private UserMapper userMapper;

/**

* 该方法使用@Transactional注解,表示该方法受事务管理。

* 当RuntimeException抛出时,Spring 会自动回滚事务,insert操作不会持久化到数据库

* @param user

*/

@Override

@Transactional

public void insertUser(User user) {

userMapper.insertUser(user);

throw new RuntimeException("模拟异常");

}

}

(2)指定回滚条件

默认情况下, checked exception 异常抛出不会引起事务回滚,但是可以通过 rollbackFor 属性显式指定需要回滚的异常类型 。

@Service

public class UserServiceImpl extends ServiceImpl implements IUserService {

@Autowired

private UserMapper userMapper;

/**

* 该方法使用@Transactional注解,表示该方法受事务管理。

* 使用rollbackFor属性设置触发事务回滚异常类型

* 当checked exception抛出时,Spring 会自动回滚事务,insert操作不会持久化到数据库

* @param user

*/

@Override

@Transactional(rollbackFor = Exception.class)

public void insertUser(User user) {

userMapper.insertUser(user);

throw new Exception("模拟异常");

}

}

2、编程式事务回滚示例

Spring 提供了 TransactionTemplate 类,用于编程式管理事务。我们可以显式捕获异常并手动控制事务的提交或回滚。

@Service

public class UserServiceImpl extends ServiceImpl implements IUserService {

@Autowired

private UserMapper userMapper;

@Autowired

private TransactionTemplate transactionTemplate;

/**

* 通过transactionTemplate声明事务逻辑

* 当异常抛出时,通过transactionStatus.setRollbackOnly()手动触发事务回滚

* @param user

*/

@Override

public void insertUser(User user) {

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

@Override

protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {

try {

userMapper.insertUser(user);

throw new RuntimeException("模拟异常");

}catch (Exception e){

//事务回滚

transactionStatus.setRollbackOnly();

}

}

});

}

}

五、事务回滚注意事项

1、异常传播问题

当异常被捕获,但是异常未抛出时也不会触发事务回滚。

@Service

public class UserServiceImpl extends ServiceImpl implements IUserService {

@Autowired

private UserMapper userMapper;

@Autowired

private TransactionTemplate transactionTemplate;

@Override

@Transactional

public void insertUser(User user) {

try {

userMapper.insertUser(user);

throw new RuntimeException("模拟异常");

}catch (Exception e){

//只捕获了异常,没有抛出,不会触发事务回滚

log.error("事务回滚"+e.getMessage());

}

}

}

解决方法:捕获异常后重新抛出,或直接让异常传播。

@Service

public class UserServiceImpl extends ServiceImpl implements IUserService {

@Autowired

private UserMapper userMapper;

@Autowired

private TransactionTemplate transactionTemplate;

@Override

@Transactional

public void insertUser(User user) {

try {

userMapper.insertUser(user);

throw new RuntimeException("模拟异常");

}catch (Exception e){

log.error("事务回滚"+e.getMessage());

//触发事务回滚

throw e;

}

}

}

2、自调用导致事务失效

Spring 事务依赖 AOP 实现,如果同一个类中自调用事务方法,事务可能失效。

@Service

public class UserServiceImpl extends ServiceImpl implements IUserService {

@Autowired

private UserMapper userMapper;

@Autowired

private TransactionTemplate transactionTemplate;

@Autowired

private IUserService userService;

@Override

@Transactional

public void updateUser(User user) {

userMapper.updateUser(user);

//调用同一个类中的方法,会导致事务失效

user.setName("调用方法");

userService.insertUser(user);

}

@Override

@Transactional

public void insertUser(User user) {

userMapper.insertUser(user);

throw new RuntimeException("模拟异常");

}

}

解决方法:

将 insertUser移到另一个服务类,由代理对象调用。使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 强制新建事务。六、总结

使用Spring事务机制,可以使我们不再需要手动编写复杂的事务管理代码,而是通过简单的配置和注解来实现事务的管理,提高开发效率和代码的可维护性。同时,Spring的事务机制还支持多种数据访问框架,如JDBC、Hibernate、MyBatis等,对事务管理变得更加灵活和易用。

相关推荐

龙之谷手游龙币怎么得 龙币哪里获取详解 365体育官网登录

龙之谷手游龙币怎么得 龙币哪里获取详解

📅 07-09 👁️ 1238
萌師在上 365bet手机在线网页

萌師在上

📅 06-29 👁️ 9640
筷子兄弟的歌 365bet手机在线网页

筷子兄弟的歌

📅 07-06 👁️ 7573