Spring:对已检查的异常进行自动回滚

时间:2017-07-04 06:54:13

标签: java spring transactional

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

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

3 个答案:

答案 0 :(得分:8)

使用@Transactional不能用于应用程序级别,但您可以:

变体1:扩展@Transactional注释并将其作为rollbackfor的默认值。但是只设置你需要的rollbackFor unchecked异常。这样你就可以控制回滚只针对你确定的情况,并避免复制过去@Transactional(rollbackFor = MyCheckedException.class)

像:

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

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

变体2:您可以从AnnotationTransactionAttributeSource创建扩展名并覆盖方法determineTransactionAttribute:

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

TransactionAttribute参见TransactionAttribute api,有一个方法

  

boolean rollbackOn(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 );
       }
};

}

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

答案 1 :(得分:1)

此配置可以解决该问题:

@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;
                        }
                    };
                }
            }
        };
    }
}

答案 2 :(得分:0)

这是与 this answer 类似的方法,即全局更改默认值,但对 Spring 配置的更改尽可能小,并且仍然可以像往常一样自定义每个方法的回滚规则(使用 {{1 }}、rollbackFor 等)。

这是通过简单地为 noRollbackFor 添加一个默认的回滚规则来实现的。由于规则根据异常类层次结构具有优先级(适用于最具体异常类的规则获胜),如果注解上没有定义其他规则,则新规则的优先级基本上最低。

Exception.class