跳至主要內容

Spring中事务的处理

logycoconut关于技术SpringDataJpaSpring大约 2 分钟

注解式事务

@Transactional 源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";

    Propagation propagation() default Propagation.REQUIRED;

    Isolation isolation() default Isolation.DEFAULT;

    int timeout() default -1;

    boolean readOnly() default false;

    Class<? extends Throwable>[] rollbackFor() default {};

    String[] rollbackForClassName() default {};

    Class<? extends Throwable>[] noRollbackFor() default {};

    String[] noRollbackForClassName() default {};
}

常用参数说明

参数名称功能描述
readOnly设置当前事务是否为只读事务
rollbackFor设置需要进行回滚的异常类数组
rollbackForClassName设置需要进行回滚的异常类名称数组
noRollbackFor设置不需要进行回滚的异常类数组
noRollbackForClassName设置不需要进行回滚的异常类名称数组
propagation设置事务的传播行为
isolation设置底层数据库的事务隔离级别,通常使用数据库的默认隔离级别
timeout设置事务的超时秒数,默认为-1,表示永不超时
transactionManager指定transactionManager,当有多个datasource时

propagation 的值

  • REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
  • SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
  • MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
  • REQUIRED_NEW:创建一个新事务,如果当前存在事务,则把当前事务挂起
  • NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起
  • NEVER:以非事务方式运行,如果当前存在事务,则抛出异常
  • NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于REQUIRED

声明式事务

又叫隐式事务,或者叫ASPECTJ事务

@Configuration
@EnableTransactionManagement
public class AspectJTransactionConfig {

    /**
     * 表示com.example.demo.service包下的所有类的所有方法
     */
    private static final String TRANSACTION_EXECUTION = "execution (* com.example.demo.service.*.*(..))";

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor() {
        // 1. 配置切入点表达式
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(TRANSACTION_EXECUTION);

        // 2. 配置事务通知
        NameMatchTransactionAttributeSource attributes = new NameMatchTransactionAttributeSource();

        // 2.1 配置事务传播属性
        RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
        readOnlyTx.setReadOnly(true);
        readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);

        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
        requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        requiredTx.setTimeout(5);

        Map<String, TransactionAttribute> txMap = new HashMap<>();
        txMap.put("add*", requiredTx);
        txMap.put("save*", requiredTx);
        txMap.put("insert*", requiredTx);
        txMap.put("update*", requiredTx);
        txMap.put("delete*", requiredTx);
        txMap.put("get*", readOnlyTx);
        txMap.put("query*", readOnlyTx);
        attributes.setNameMap(txMap);

        TransactionInterceptor txAdvice = new TransactionInterceptor();
        txAdvice.setTransactionManager(transactionManager);
        txAdvice.setTransactionAttributeSource(attributes);

        // 3. 配置advisor
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(pointcut);
        advisor.setAdvice(txAdvice);

        return advisor;
    }

}