Java 每当我说@Transactional 时,回滚每个已检查的异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3701376/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rollback on every checked exception, whenever I say @Transactional
提问by pihentagy
Since the programmer is forced to catch all checked exception, I to throw checked exception in case of any problem. I would like to rollback on any of those expections. Writing rollbackFor=Exception.class
on every @Transactional
annotation is very error-prone, so I would like to tell spring, that: "whenever I write @Transactional
, I mean @Transactional(rollbackFor=Exception.class)
".
由于程序员被迫捕获所有已检查的异常,因此如果出现任何问题,我将抛出已检查的异常。我想回滚这些期望中的任何一个。rollbackFor=Exception.class
在每一个@Transactional
注解上写都是很容易出错的,所以我想告诉spring,“每当我写的时候@Transactional
,我的意思是@Transactional(rollbackFor=Exception.class)
”。
I know, that I could create a custom annotation, but that seems unnatural.
我知道,我可以创建自定义注释,但这似乎不自然。
So is there a way to tell spring how it should handle checked excpetions globally?
那么有没有办法告诉 spring 它应该如何处理全局检查的异常?
采纳答案by Sean Patrick Floyd
Custom Shortcut Annotations
自定义快捷方式注释
I know, that I could create a custom annotation, but that seems unnatural.
我知道,我可以创建自定义注释,但这似乎不自然。
No, this is exactly the use case for a Custom Annotation. Here's a quote from Custom Shortcut Annotationsin the Spring Reference:
不,这正是自定义注释的用例。这是Spring 参考中自定义快捷方式注释的引用:
If you find you are repeatedly using the same attributes with @Transactional on many different methods, then Spring's meta-annotation support allows you to define custom shortcut annotations for your specific use cases.
如果您发现在许多不同的方法上重复使用带有 @Transactional 的相同属性,那么 Spring 的元注释支持允许您为特定用例定义自定义快捷注释。
Sample Code
示例代码
And here's a sample annotation for your use case:
这是您的用例的示例注释:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor=Exception.class)
public @interface MyAnnotation {
}
Now annotate your services and / or methods with @MyAnnotation
(you'll think of a better name). This is well-tested functionality that works by default. Why re-invent the wheel?
现在用@MyAnnotation
(你会想到一个更好的名字)来注释你的服务和/或方法。这是经过充分测试的功能,默认情况下有效。为什么要重新发明轮子?
回答by Bozho
You can:
你可以:
- catch and wrap the checked exception into an unchecked exception -
throw new RuntimeException(checkedException)
- create a proxy around the method, using
MethodInterceptor
(or@AroundInvoke
, or any other means to create aspects in spring), declare it to be executed before the<tx:annotation-driven />
by specifyingorder="1"
andorder="2"
and catch and wrap there.
- 捕获已检查的异常并将其包装到未检查的异常中 -
throw new RuntimeException(checkedException)
- 围绕该方法创建一个代理,使用
MethodInterceptor
(或@AroundInvoke
,或任何其他方式在 spring 中创建方面),<tx:annotation-driven />
通过指定order="1"
andorder="2"
并在那里捕获和包装来声明它在 之前执行。
回答by oksayt
Looks like you can configure a transactional advice based on method name like this: (from the Spring 2.0 docs)
看起来您可以像这样根据方法名称配置事务性建议:(来自Spring 2.0 文档)
Exactly which Exception types mark a transaction for rollback can be configured. Find below a snippet of XML configuration that demonstrates how one would configure rollback for a checked, application-specific Exception type.
可以配置究竟哪些异常类型将事务标记为回滚。在下面找到一段 XML 配置片段,该片段演示了如何为已检查的、特定于应用程序的异常类型配置回滚。
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="false" rollback-for="NoProductInStockException"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
回答by axtavt
Approach with custom annotation looks good and straightforward, but if you actually don't want to use it, you can create a custom TransactionAttributeSource
to modify interpretation of @Transactional
:
使用自定义注释的方法看起来不错且简单明了,但如果您实际上不想使用它,您可以创建一个自定义TransactionAttributeSource
来修改对 的解释@Transactional
:
public class RollbackForAllAnnotationTransactionAttributeSource
extends AnnotationTransactionAttributeSource {
@Override
protected TransactionAttribute determineTransactionAttribute(
AnnotatedElement ae) {
TransactionAttribute target = super.determineTransactionAttribute(ae);
if (target == null) return null;
else return new DelegatingTransactionAttribute(target) {
@Override
public boolean rollbackOn(Throwable ex) {
return true;
}
};
}
}
And instead of <tx:annotation-driven/>
you configure it manually as follows (see source of AnnotationDrivenBeanDefinitionParser
):
而不是<tx:annotation-driven/>
您手动配置它如下(见来源AnnotationDrivenBeanDefinitionParser
):
<bean id = "txAttributeSource"
class = "RollbackForAllAnnotationTransactionAttributeSource" />
<bean id = "txInterceptor"
class = "org.springframework.transaction.interceptor.TransactionInterceptor">
<property name = "transactionManagerBeanName" value = "transactionManager" />
<property name = "transactionAttributeSource" ref = "txAttributeSource" />
</bean>
<bean
class = "org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor">
<property name="transactionAttributeSource" ref = "txAttributeSource" />
<property name = "adviceBeanName" value = "txInterceptor" />
</bean>
Also you need <aop:config/>
or <aop:aspectj-autoproxy />
.
您还需要<aop:config/>
或<aop:aspectj-autoproxy />
。
However note that such overrides may be confusing for other developers who expect a normal behaviour of @Transactional
.
但是请注意,对于其他期望@Transactional
.