Rollback on every checked exception, whenever I say @Transactional

前端 未结 4 581
有刺的猬
有刺的猬 2020-12-02 17:04

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. Writ

相关标签:
4条回答
  • 2020-12-02 17:30

    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 Annotations in the Spring Reference:

    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.

    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?

    0 讨论(0)
  • 2020-12-02 17:35

    Looks like you can configure a transactional advice based on method name like this: (from the Spring 2.0 docs)

    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.

    <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>
    
    0 讨论(0)
  • 2020-12-02 17:45

    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 specifying order="1" and order="2" and catch and wrap there.
    0 讨论(0)
  • 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:

    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):

    <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 />.

    However note that such overrides may be confusing for other developers who expect a normal behaviour of @Transactional.

    0 讨论(0)
提交回复
热议问题