プログラマーはすべてのチェック済み例外をキャッチする必要があるため、問題が発生した場合はチェック済み例外をスローします。私はそれらの期待のいずれかにロールバックしたいと思います。すべての_rollbackFor=Exception.class
_アノテーションに_@Transactional
_を書き込むと、エラーが発生しやすくなるので、「_@Transactional
_を書くときはいつでも、@Transactional(rollbackFor=Exception.class)
」ということを春に伝えたいと思います。
カスタムアノテーションを作成できることはわかっていますが、それは不自然に思えます。
それで、春にチェックされた例外をどのように処理するべきかを伝える方法はありますかglobally?
カスタムアノテーションを作成できることはわかっていますが、それは不自然に思えます。
いいえ、これはまさにカスタムアノテーションの使用例です。 Spring Referenceの Custom Shortcut Annotations からの引用は次のとおりです。
多くの異なるメソッドで@Transactionalを使用して同じ属性を繰り返し使用している場合、Springのメタアノテーションサポートにより、特定のユースケースにカスタムショートカットアノテーションを定義できます。
ユースケースのサンプルアノテーションを次に示します。
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor=Exception.class)
public @interface MyAnnotation {
}
次に、サービスやメソッドに@MyAnnotation
で注釈を付けます(より適切な名前を考えます)。これは、デフォルトで機能する十分にテストされた機能です。なぜ車輪を再発明するのですか?
カスタムアノテーションを使用したアプローチは見た目は簡単ですが、実際に使用したくない場合は、カスタム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;
}
};
}
}
そして、<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>
また、<aop:config/>
または<aop:aspectj-autoproxy />
も必要です。
ただし、そのようなオーバーライドは、@Transactional
の通常の動作を期待する他の開発者を混乱させる可能性があることに注意してください。
次のように、メソッド名に基づいてトランザクションアドバイスを設定できるようです((- Spring 2.0のドキュメント から))
どの例外タイプがトランザクションをロールバックにマークするかを正確に設定できます。以下は、チェックされたアプリケーション固有の例外タイプのロールバックを構成する方法を示す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>
あなたはできる:
throw new RuntimeException(checkedException)
MethodInterceptor
(または@AroundInvoke
、またはその他の方法で春にアスペクトを作成する)を使用して、メソッドの周りにプロキシを作成し、<tx:annotation-driven />
の前に実行するように宣言し、order="1"
とorder="2"
を指定して、そこでキャッチしてラップします。