当我们在使用Spring框架时,事务管理是一个非常重要的概念。Spring提供了多种方式来处理事务,其中注解方式是一种常用的方式,因为它可以大大简化我们的配置和开发过程。
下面,我会详细讲解如何使用注解方式处理事务,并且提供两个示例。
1. 配置数据源和事务管理器
首先,我们需要配置数据源和事务管理器,这里以MySQL数据库为例。在Spring中配置数据源和事务管理器通常使用XML配置,在这里我们使用Java配置方式。
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}
上面的配置使用了Apache的BasicDataSource和Spring的DataSourceTransactionManager。
2. 添加@Transactional注解
启用注解方式处理事务只需要在方法上添加@Transactional注解即可,这个注解来自于Spring的@Transactional包,它可以应用于类和方法。
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Transactional
@Override
public void save(User user) {
userMapper.insert(user);
// 抛出一个异常用于测试事务回滚
throw new RuntimeException("保存用户失败");
}
}
在上面的示例中,我们调用了userMapper的insert方法插入一个用户,然后抛出了一个RuntimeException用于测试事务回滚。由于save方法被匹配了@Transactional注解,当抛出异常时,该方法执行的操作将被回滚。
3. 配置声明式事务
在我们的实际开发中,很少出现直接将@Transactional注解添加到服务实现的情况。通常我们使用声明式事务配置来统一管理所有的事务处理。声明式事务是一种切面,用于拦截特定的方法调用,并在调用前后开启和提交或回滚事务。
在Spring中,声明式事务可以使用XML配置,或者像上面的Java配置方式。我们这里使用Java配置方式。
@Configuration
@EnableTransactionManagement
@MapperScan("com.example.mapper")
public class TransactionConfig {
@Autowired
private DataSource dataSource;
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public TransactionInterceptor txAdvice() {
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
DefaultTransactionAttribute readOnly = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_SUPPORTS);
DefaultTransactionAttribute required = new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED);
required.setReadOnly(false);
RuleBasedTransactionAttribute requiredRule = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED, Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
Map<String, TransactionAttribute> mappedAttributes = new HashMap<>();
mappedAttributes.put("save*", requiredRule);
mappedAttributes.put("update*", requiredRule);
mappedAttributes.put("delete*", requiredRule);
mappedAttributes.put("get*", readOnly);
source.setNameMap(mappedAttributes);
return new TransactionInterceptor(transactionManager(), source);
}
@Bean
public Advisor txAdviceAdvisor() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* com.example.service.*.*(..))");
return new DefaultPointcutAdvisor(pointcut, txAdvice());
}
}
上面的示例,我们使用@EnableTransactionManagement来启用声明式事务。我们使用了DefaultTransactionAttribute和RuleBasedTransactionAttribute来配置事务的传播级别和回滚规则。在txAdviceAdvisor方法中,我们指定了一个切点表达式来拦截com.example.service包中的所有方法。
这里提供第二个示例:
@Service
public class UserAddressServiceImpl implements UserAddressService {
@Autowired
private UserAddressMapper userAddressMapper;
@Transactional
@Override
public void save(UserAddress userAddress) {
userAddressMapper.insert(userAddress);
}
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private UserAddressService userAddressService;
@Transactional
@Override
public void save(User user, List<UserAddress> userAddresses) {
userMapper.insert(user);
for (UserAddress userAddress : userAddresses) {
userAddressService.save(userAddress);
}
}
}
在上面的示例中,我们添加了一个save方法用于保存一个用户以及该用户的地址信息。在save方法中,我们首先将用户信息插入到数据库中,然后遍历用户地址列表,调用userAddressService的save方法来保存用户地址。由于save方法上标有@Transactional注解,当保存用户或用户地址中的任何一个操作失败时,整个事务将被回滚。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring使用注解方式处理事务 - Python技术站