将Spring配置为在非RuntimeExceptions
上回滚的一种方法是在服务类上使用@Transactional(rollbackFor=...)
注释。这种方法的问题是我们需要为几乎所有似乎真正冗余的服务类定义(rollbackFor = ...)。
我的问题:是否有任何方法可以配置Spring事务管理器的默认行为,以便在非RuntimeException
上发生回滚,而不会在每个@Transactional
注释上声明它。类似于在EJB中的异常类上使用@ApplicationException(rollback=true)
注释。
答案 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