春季:检查异常时自动回滚

2022-09-03 06:05:31

将 Spring 配置为在非上回滚的一种方法是在服务类上使用注释。这种方法的问题在于,我们需要为几乎所有的服务类定义(rollbackFor=...),这似乎真的是多余的。RuntimeExceptions@Transactional(rollbackFor=...)


我的问题是:有没有办法为Spring事务管理器配置一个默认行为,以便在发生非时回滚,而无需在每个注释上声明它。类似于在 EJB 中的异常类上使用注解。RuntimeException@Transactional@ApplicationException(rollback=true)


答案 1

对于应用程序级别,您无法使用 @Transactional 执行此操作,但您可以:

变体 1 :扩展@Transactional注释,并将其作为回滚的默认值。但是设置回滚对于仅需要的未选中的异常。有了这个,你可以控制回滚,只在你确定的情况下,并避免复制过去的@Transactional(rollbackFor = MyCheckedException.class)

喜欢:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor=MyCheckedException.class)
public @interface TransactionalWithRollback {
}

并使用此注释而不是标准@Transactional。

变体 2 :您可以从 AnnotationTransactionAttributeSource 创建扩展,并覆盖方法确定TransactionAttribute:

protected TransactionAttribute  determineTransactionAttribute(AnnotatedElement ae)
//Determine the transaction attribute for the given method or class.

TransactionAttribute 参见 TransactionAttribute api,有一种方法

布尔回滚On(Throwable ex)我们应该在给定的异常上回滚吗?

protected TransactionAttribute determineTransactionAttribute(
    AnnotatedElement ae) {
    return new DelegatingTransactionAttribute(target) {
        @Override
        public boolean rollbackOn(Throwable ex) {
           return (check is exception type as you need for rollback );
       }
};

}

第二种方法不如第一种方法好,因为你对事务管理器来说真的是全局性的。最好使用自定义注释,因为您可以控制它,只适用于您真正需要它的方法/类。但是,如果您需要它,在任何情况下使用第二种变体,这将是您默认的跨国行为。


答案 2

这个配置解决了这个问题:

@Configuration
public class MyProxyTransactionManagementConfiguration extends ProxyTransactionManagementConfiguration {

    @Bean
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource() {

            @Nullable
            protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
                TransactionAttribute ta = super.determineTransactionAttribute(element);
                if (ta == null) {
                    return null;
                } else {
                    return new DelegatingTransactionAttribute(ta) {
                        @Override
                        public boolean rollbackOn(Throwable ex) {
                            return super.rollbackOn(ex) || ex instanceof Exception;
                        }
                    };
                }
            }
        };
    }
}

推荐