1. 概要

This tutorial will discuss the right way to configure Spring Transactions, how to use the @Transactional annotation and common pitfalls.

コアの永続性構成の詳細については、 SpringwithJPAチュートリアルを確認してください。

Basically, there are two distinct ways to configure Transactions, annotations and AOP, each with its own advantages. We’re going to discuss the more common annotation config here.

2. トランザクションの構成

Spring 3.1では、トランザクションサポートを有効にするために@Configurationクラスで使用できる@EnableTransactionManagementアノテーションが導入されています。

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig{

   @Bean
   public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
       //...
   }

   @Bean
   public PlatformTransactionManager transactionManager() {
      JpaTransactionManager transactionManager = new JpaTransactionManager();
      transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
      return transactionManager;
   }
}

ただし、 Spring Bootプロジェクトを使用していて、クラスパスにspring-data- *またはspring-txの依存関係がある場合、トランザクション管理はデフォルトで有効になります

3. XMLを使用してトランザクションを構成する

For versions before 3.1, or if Java is not an option, here is the XML configuration using annotation-driven and namespace support:

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
   <property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

4. @Transactionalアノテーション

トランザクションが構成されたら、クラスレベルまたはメソッドレベルで@Transactionalを使用してBeanにアノテーションを付けることができます。

@Service
@Transactional
public class FooService {
    //...
}

注釈は、追加の構成もサポートします。

  • トランザクションの伝搬タイプ
  • トランザクションの分離レベル
  • トランザクションによってラップされた操作のタイムアウト
  • readOnlyフラグ–トランザクションを読み取り専用にする必要があるという永続性プロバイダーへのヒント
  • トランザクションのロールバックルール

デフォルトでは、ロールバックは実行時に発生し、チェックされていない例外のみが発生することに注意してください。 チェックされた例外は、トランザクションのロールバックをトリガーしません。 もちろん、この動作はrollbackForおよびnoRollbackForアノテーションパラメーターを使用して構成できます。

5. 潜在的な落とし穴

5.1. トランザクションとプロキシ

大まかに言うと、 Springは、クラスまたは任意のメソッドのいずれかで、@Transactionalで注釈が付けられたすべてのクラスのプロキシを作成します。 プロキシを使用すると、フレームワークは、主にトランザクションの開始とコミットのために、実行中のメソッドの前後にトランザクションロジックを挿入できます。

覚えておくべき重要なことは、トランザクションBeanがインターフェースを実装している場合、デフォルトではプロキシはJava動的プロキシになるということです。 これは、プロキシを介して着信する外部メソッド呼び出しのみがインターセプトされることを意味します。 メソッドに@Transactionalアノテーションが付いている場合でも、自己呼び出し呼び出しはトランザクションを開始しません。

プロキシを使用する際のもう1つの注意点は、パブリックメソッドのみに@Transactionalのアノテーションを付ける必要があることです。他の可視性のメソッドは、プロキシされていないため、アノテーションを黙って無視します。

5.2. 分離レベルの変更

courseDao.createWithRuntimeException(course);

トランザクション分離レベルを変更することもできます。

@Transactional(isolation = Isolation.SERIALIZABLE)

これは実際にはSpring4.1で導入されたことに注意してください。 上記の例をSpring4.1より前に実行すると、次のようになります。

org.springframework.transaction.InvalidIsolationLevelException: Standard JPA does not support custom isolation levels – use a special JpaDialect for your JPA implementation

5.3. 読み取り専用トランザクション

readOnly フラグは通常、特にJPAを使用している場合に、混乱を引き起こします。 Javadocから:

This just serves as a hint for the actual transaction subsystem; it will not necessarily cause failure of write access attempts. A transaction manager which cannot interpret the read-only hint will not throw an exception when asked for a read-only transaction.

The fact is that we can’t be sure that an insert or update won’t occur when the readOnly flag is set. This behavior is vendor-dependent, whereas JPA is vendor agnostic.

readOnlyフラグはトランザクション内でのみ関連することを理解することも重要です。操作がトランザクションコンテキスト外で発生した場合、フラグは単に無視されます。 その簡単な例では、次の注釈が付いたメソッドを呼び出します。

@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)

非トランザクションコンテキストからは、トランザクションは作成されず、readOnlyフラグは無視されます。

5.4. トランザクションログ

A helpful method to understand transactional-related issues is fine-tuning logging in the transactional packages. Springの関連パッケージは「 org.springframework.transaction」 、ログレベルを設定する必要があります痕跡。

5.5. トランザクションのロールバック

@Transactional アノテーションは、メソッドのトランザクションのセマンティクスを指定するメタデータです。 トランザクションをロールバックするには、宣言型とプログラム型の2つの方法があります。

宣言型アプローチでは、@ Transactionalアノテーションでメソッドにアノテーションを付けます。 @Transactional アノテーションは、属性rollbackForまたはrollbackForClassNameを使用してトランザクションをロールバックし、属性noRollbackForまたはnoRollbackForClassNameを使用しますリストされた例外でのロールバックを回避します。

宣言型アプローチのデフォルトのロールバック動作は、実行時の例外でロールバックします。

宣言型アプローチを使用して、実行時の例外またはエラーのトランザクションをロールバックする簡単な例を見てみましょう。

@Transactional
public void createCourseDeclarativeWithRuntimeException(Course course) {
    courseDao.create(course);
    throw new DataIntegrityViolationException("Throwing exception for demoing Rollback!!!");
}

Next, we’ll use the declarative approach to rollback a transaction for the listed checked exceptions. ロールバックin私たちのon [ X97X] SQLException :

@Transactional(rollbackFor = { SQLException.class })
public void createCourseDeclarativeWithCheckedException(Course course) throws SQLException {
    courseDao.create(course);
    throw new SQLException("Throwing exception for demoing rollback");
}

リストされた例外のトランザクションのロールバックを防ぐための宣言型アプローチでの属性noRollbackForの簡単な使用法を見てみましょう。

@Transactional(noRollbackFor = { SQLException.class })
public void createCourseDeclarativeWithNoRollBack(Course course) throws SQLException {
    courseDao.create(course);
    throw new SQLException("Throwing exception for demoing rollback");
}

プログラムによるアプローチでは、TransactionAspectSupportを使用してトランザクションをロールバックします。

public void createCourseDefaultRatingProgramatic(Course course) {
    try {
       courseDao.create(course);
    } catch (Exception e) {
       TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}
d 宣言的ロールバック戦略 したほうがいい なれ 好意 プログラマティック以上 ロールバック戦略.

6. 結論

この記事では、JavaとXMLの両方を使用したトランザクションセマンティクスの基本構成について説明しました。 また、 @ Transactional、の使用方法と、トランザクション戦略のベストプラクティスについても学びました。

いつものように、この記事で紹介するコードは、Githubから入手できます。