目录
事务管理概述
如何使用@Transactional注解
事务管理的传播行为
事务隔离级别
事务的嵌套
手动提交事务
手动回滚事务
注解方式嵌套事务
事务管理的异常处理
在@Transactional注解中指定回滚策略
使用try-catch
自定义异常处理器
创建自定义异常类
编写自定义异常处理器类
在@Transactional注解中指定自定义异常处理器
在关系型数据库中,事务是指一组相关的操作,这些操作被看作单个逻辑单元并且要么全部执行成功,要么全部回滚。事务管理就是保证所有操作都能够原子性地进行,即要么全部成功,要么全部失败。
在Spring Boot中,我们可以使用@Transactional注解来启用事务管理。当使用@Transactional注解时,Spring会将方法包装在一个事务中,并在方法执行期间自动处理事务提交或回滚。
在Spring Boot中使用@Transactional注解非常简单。只需将@Transactional注解添加到要进行事务管理的方法上即可。例如:
@Service
public class MyService {
@Autowired
private SomeRepository someRepository;
@Transactional
public void doSomething() {
// 执行一些业务逻辑
someRepository.save(entity1);
someRepository.save(entity2);
// 如果任何一个保存操作失败,则整个事务都会回滚。
}
}
在上面的示例中,当方法doSomething()被调用时,Spring将自动为该方法创建一个事务。如果该方法执行过程中有任何异常抛出,那么整个事务都将被回滚,所有已经执行的保存操作也会被回滚。
Spring Boot中的@Transactional注解有一个非常强大的特性,即可以控制事务的传播行为。传播行为定义了事务如何在嵌套的方法调用中进行传递。
除了传播行为之外,事务还有一个重要的概念,即隔离级别。隔离级别定义了多个并发事务之间应该如何相互隔离。Spring Boot支持以下五种隔离级别:
可以使用@Transactional注解的isolation属性指定要使用的隔离级别。例如:
@Service
public class MyService {
@Transactional(isolation = Isolation.READ_COMMITTED)
public void doSomething() {
// 执行业务逻辑
}
}
当一个方法内部调用另一个被@Transactional注解标记的方法时,会发生事务的嵌套。如果在内部方法中启动了新事务,则新事务将成为当前事务的子事务。
在子事务完成后,可以选择回滚该子事务或将其提交到父事务中。如果父事务成功提交,则所有子事务都将一起提交;如果父事务失败回滚,则所有子事务也将一起回滚。
下面是一个示例代码:
@Service
public class MyService {
@Autowired
private SomeRepository someRepository;
// 外层事务
@Transactional
public void doSomething() {
someRepository.save(entity1);
try {
// 内层事务
doSomeOtherThing();
} catch (Exception e) {
// 内层事务抛出异常,外层事务回滚
}
}
// 内层事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomeOtherThing() {
someRepository.save(entity2);
// 如果这里抛出异常,则整个内嵌事务会被回滚
}
}
在上面的示例中,doSomething()方法使用REQUIRED事务传播行为启用了一个外层事务,然后调用了doSomeOtherThing()方法,doSomeOtherThing()方法使用REQUIRES_NEW事务传播行为启用了一个内层事务。
如果在doSomething()方法中发生异常,则整个外层事务将被回滚,包括所有的子事务。如果在doSomeOtherThing()方法中发生异常,则只会回滚内层事务,而外层事务不受影响。
需要注意的是,在使用嵌套事务时,仅有@Transactional注解标记的方法才会产生事务。如果内部方法没有被@Transactional注解标记,则不会启动新的事务,事务的传播行为也就失去了意义。
下面是一个示例代码:
@Service
public class MyService {
@Autowired
private SomeRepository someRepository;
@Autowired
private PlatformTransactionManager transactionManager;
// 外层事务
public void doSomething() {
TransactionTemplate template = new TransactionTemplate(transactionManager);
template.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
someRepository.save(entity1);
try {
// 内层事务
doSomeOtherThing();
// 如果内层事务成功,则手动提交外层事务
status.flush();
} catch (Exception e) {
// 内层事务抛出异常,外层事务回滚
status.setRollbackOnly();
}
}
});
}
// 内层事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomeOtherThing() {
someRepository.save(entity2);
// 如果这里抛出异常,则整个内嵌事务会被回滚
}
}
在上面的示例中,doSomething()方法使用TransactionTemplate对象手动执行事务操作,对于内层事务,再次使用@Transactional注解进行管理。如果内层事务成功,则手动提交外层事务;如果内层事务失败,则手动回滚外层事务。
下面是一个手动回滚事务的示例代码:
@Service
public class MyService {
@Autowired
private SomeRepository someRepository;
@Autowired
private PlatformTransactionManager transactionManager;
// 外层事务
public void doSomething() {
TransactionTemplate template = new TransactionTemplate(transactionManager);
template.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
someRepository.save(entity1);
try {
// 内层事务
doSomeOtherThing();
// 如果内层事务成功,则手动提交外层事务
status.flush();
} catch (Exception e) {
// 内层事务抛出异常,手动回滚所有事务
status.setRollbackOnly();
throw e;
}
}
});
}
// 内层事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomeOtherThing() {
someRepository.save(entity2);
// 如果这里抛出异常,则整个内嵌事务会被回滚
}
}
在上面的示例中,如果发生了任何异常,则手动回滚所有事务。在回滚时,需要将事务状态设置为rollback-only,以便Spring自动回滚所有连接的事务。
需要注意的是,手动提交和回滚事务通常不是必要的,只有在特殊情况下才使用。在大多数情况下,应该让Spring自动管理事务,以便实现更好的性能和可维护性。
@Service
public class MyService {
@Autowired
private SomeRepository someRepository;
// 外层事务
@Transactional
public void doSomething() {
someRepository.save(entity1);
try {
// 内层事务
doSomeOtherThing();
} catch (Exception e) {
// 内层事务抛出异常,外层事务回滚
}
}
// 内层事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void doSomeOtherThing() {
someRepository.save(entity2);
// 如果这里抛出异常,则整个内嵌事务会被回滚
}
}
在上面的示例中,doSomething()方法使用@Transactional注解标记外层事务,然后调用了doSomeOtherThing()方法,doSomeOtherThing()方法使用REQUIRES_NEW事务传播行为启用了一个内层事务。
如果在doSomething()方法中发生异常,则整个外层事务将被回滚,包括所有的子事务。如果在doSomeOtherThing()方法中发生异常,则只会回滚内层事务,而外层事务不受影响。
@Transactional
注解中指定回滚策略可以在@Transactional
注解中使用rollbackFor
属性指定需要回滚的异常类型。例如,如果希望在发生任何RuntimeException时回滚事务,则可以添加以下代码:
@Transactional(rollbackFor = RuntimeException.class)
在Spring Boot中,可以使用try-catch块来处理业务逻辑中可能出现的异常。当抛出异常时,可以手动回滚事务以确保数据的一致性。例如,以下代码演示了如何在发生异常时回滚事务:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void save(User user) {
try {
// 保存用户信息
userRepository.save(user);
} catch (Exception e) {
// 回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw e;
}
}
}
在Spring Boot的事务管理中,可以使用自定义异常处理器来处理特定类型的异常。自定义异常处理器是实现org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionExceptionHandler
接口的类。在该接口中,只有一个方法handleException()
,用于处理发生的异常。
下面是在Spring Boot中使用自定义异常处理器进行事务管理的步骤:
首先,需要创建一个自定义异常类来处理特定类型的异常。例如,以下代码演示了如何创建一个UserNotFoundException
异常类:
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
接下来,需要编写一个实现TransactionExceptionHandler
接口的类来处理自定义异常。在该类中,需要实现handleException()
方法,用于根据异常类型执行相应的回滚或提交操作。例如,以下代码演示了如何创建一个自定义异常处理器:
@Component
public class CustomTransactionExceptionHandler implements TransactionExceptionHandler {
@Override
public void handleException(Throwable ex) throws Throwable {
if (ex instanceof UserNotFoundException) {
// 如果抛出的异常是UserNotFoundException,则回滚事务
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw ex;
} else {
// 对其他异常进行默认的处理
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
throw new RuntimeException(ex);
}
}
}
在这个例子中,我们判断了抛出的异常是否是UserNotFoundException
,如果是,则回滚事务并重新抛出此异常。否则,我们将使用默认的处理方式(即回滚事务并重新抛出RuntimeException)。
@Transactional
注解中指定自定义异常处理器最后,在使用@Transactional
注解时,需要在该注解中指定自定义异常处理器。例如,以下代码演示了如何在UserService
类中使用自定义异常处理器:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional(rollbackFor = RuntimeException.class, exceptionHandler = CustomTransactionExceptionHandler.class)
public void save(User user) {
// 保存用户信息
userRepository.save(user);
if (user.getId() == null) {
throw new UserNotFoundException("User not found!");
}
}
}
在这个例子中,我们在@Transactional
注解中指定了自定义异常处理器CustomTransactionExceptionHandler.class
。当抛出UserNotFoundException
异常时,将会执行自定义异常处理器中指定的操作。
通过以上步骤,可以在Spring Boot应用程序中使用自定义异常处理器来进行事务管理,并针对特定类型的异常进行相应的处理。