在Spring框架中,@Transactional注解是用来管理事务的关键注解之一。本文将详细解释@Transactional注解的作用、属性和使用方法,并提供代码实例来演示其在实际项目中的应用。
@Transactional注解用于声明一个方法需要在一个事务中执行,当方法被调用时,Spring会自动创建一个事务并在方法执行完毕后根据方法的执行结果来提交或回滚事务。
@Transactional注解有许多属性可以用来定制事务的行为,其中一些常用属性包括:
propagation:事务的传播行为
isolation:事务的隔离级别
timeout:事务超时时间
readOnly:是否为只读事务
rollbackFor:指定哪些异常触发事务回滚
1、propagation(事务的传播行为)
propagation属性用于指定事务方法的传播行为,即当一个事务方法被另一个事务方法调用时,应该如何处理事务。以下是propagation属性的可选值及其含义:
Propagation.REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
Propagation.MANDATORY:强制要求当前存在事务,如果没有事务则抛出异常。
Propagation.REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则挂起当前事务。
Propagation.NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。
Propagation.NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。
Propagation.NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新事务。
2、isolation(事务的隔离级别)
isolation属性用于指定事务的隔离级别,即多个事务同时操作数据库时,事务之间的隔禜程度。以下是isolation属性的可选值及其含义:
Isolation.DEFAULT:使用数据库默认的隔离级别。
Isolation.READ_UNCOMMITTED:允许事务读取未提交的数据更改。
Isolation.READ_COMMITTED:只允许事务读取已提交的数据。
Isolation.REPEATABLE_READ:确保事务可以多次读取相同的数据,并且在事务期间数据不会被其他事务修改。
Isolation.SERIALIZABLE:确保事务可以多次读取相同的数据,并且在事务期间数据不会被其他事务修改,达到最高的隔离级别。
3、timeout(事务超时时间)
timeout属性用于指定事务的超时时间,即事务执行的最长时间。如果事务执行时间超过指定的超时时间,事务将自动回滚。timeout属性的值为秒数,默认为-1,表示没有超时限制。
4、 readOnly(是否为只读事务)
readOnly属性用于指定事务是否为只读事务,即只读取数据而不修改数据。如果将readOnly属性设置为true,则表示事务只读取数据,不会对数据进行修改;如果设置为false,则表示事务可以读取和修改数据。
5、rollbackFor(指定哪些异常触发事务回滚)
rollbackFor属性用于指定哪些异常会触发事务回滚。可以指定一个或多个异常类,当事务方法中抛出指定的异常时,事务将回滚。如果不指定任何异常类,默认只有RuntimeException及其子类会触发事务回滚。
以上是对propagation、isolation、timeout、readOnly和rollbackFor属性的详细解释及其可选值的含义。这些属性可以根据具体的业务需求来设置,以确保事务的正确性和一致性。
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public void createOrder(Order order) {
orderRepository.saveOrder(order);
}
@Transactional(rollbackFor = Exception.class)
public void cancelOrder(Long orderId) throws Exception {
Order order = orderRepository.findOrderById(orderId);
if (order.getStatus().equals("PAID")) {
throw new Exception("Order cannot be cancelled once paid");
}
order.setStatus("CANCELLED");
orderRepository.updateOrder(order);
}
}