Doorgaan naar hoofdcontent

Using spring's @transactional to only roll back when you really want to

In spring you can use the @Transactional annotation to marcate public methods as transactions.
Any exception thrown in such an exception causes a rollback... Any exception? No, spring only does so on runtime exceptions. Checked exceptions are allowed and do not result in a rollback.
And even then, you can allow some transactions to rollback, or not, with the proper properties for the transactions. For examle, @Transactional(rollbackFor="MyCheckedException.class")will rollback for a specific checked exception, and similarly, you can use @Transactional(noRollbackFor="MyUncheckedException.class") for unchecked exceptions.

Of course, you might want to make it a little simpler on yourself.
This article on stackoverflow shows us a different way: we can use our own transaction handler by overriding spring's.

Let's have a sample interface which defines whether an exception should perform a rollback:

interface ConfigurableRollback
    shouldRollbackOnException();
} 


Assume we have a class like this


public class ConfigurableRollbackTransactionAttributeSource 
    extends AnnotationTransactionAttributeSource {
    @Override
    protected TransactionAttribute determineTransactionAttribute(
            AnnotatedElement ae) {
        TransactionAttribute target = super.determineTransactionAttribute(ae);
        if (target == null) return null;
        else return new RuleBasedTransactionAttribute(target) {
            @Override
            public boolean rollbackOn(Throwable ex) {
                if (ex instanceof ConfigurableRollback) {
                    return ((ConfigurableRollback) ex).shouldRollbackOnException();
                }
                return super.rollBackOn(ex);
            }
        };
    }
}
And we do not use <tx:annotation-driven/> but instead do our own wiring:
<bean id = "txAttributeSource"
    class = "ConfigurableRollbackTransactionAttributeSource " />
<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>

Then presto, we have the option to define by exception what our rollback should be (by having the exception implement ConfigurableRollback's shouldRollbackOnException() method)

Reacties