English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Springbootのトランザクション管理の詳細解説

Spring Bootのトランザクション管理では、インターフェースPlatformTransactionManagerを実装します。

public interface PlatformTransactionManager {
  org.springframework.transaction.TransactionStatus getTransaction(org.springframework.transaction.TransactionDefinition transactionDefinition) throws org.springframework.transaction.TransactionException;
  void commit(org.springframework.transaction.TransactionStatus transactionStatus) throws org.springframework.transaction.TransactionException;
  void rollback(org.springframework.transaction.TransactionStatus transactionStatus) throws org.springframework.transaction.TransactionException;
}

springを使用する場合に-boot-starter-jdbc依存関係がある場合、フレームワークは自動的に DataSourceTransactionManager をデフォルトで注入します。したがって、追加の設定なしで @Transactional アノテーションを使用してトランザクションを使用することができます。

jdbcトランザクションマネージャー

Service内で @Transactional アノテーションが付いているメソッドはトランザクションをサポートします。アノテーションがクラスに付いている場合、そのクラスのすべてのメソッドがデフォルトでトランザクションをサポートします。

複数のトランザクションマネージャー状況

一:TransactionManagementConfigurerインターフェースを実装することで、デフォルトのトランザクションマネージャーを設定できます。

二:具体的なメソッド実行時にvalueを設定することができます。

Springコンテナに複数の PlatformTransactionManager インスタンスが存在し、TransactionManagementConfigurer インターフェースを実装していない場合、@Transactional アノテーションを使用する際にはvalueを指定する必要があります。指定しないと例外が発生します。

//@EnableTransactionManagement // 注解式事务管理を開始します。XML設定ファイルの <tx:annotation> に相当します。-driven />
@SpringBootApplication
public class ProfiledemoApplication implements TransactionManagementConfigurer {
  @Resource(name="txManager2")
  private PlatformTransactionManager txManager2;
  // 手动创建事务管理器1 datasource框架会自动注入
  //在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。
  @Bean(name = "txManager1")
  public PlatformTransactionManager txManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
  }
  // 创建事务管理器2
  @Bean(name = "txManager2")
  public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
    return new JpaTransactionManager(factory);
  }
  // 实现接口 TransactionManagementConfigurer 方法,其返回值代表在拥有多个事务管理器的情况下默认使用的事务管理器
  @Override
  public PlatformTransactionManager annotationDrivenTransactionManager() {
    return txManager2;
  }
  public static void main(String[] args) {
    SpringApplication.run(ProfiledemoApplication.class, args);
  }
}

具体实现

@Component
public class DevSendMessage implements SendMessage {
  // 使用value具体指定使用哪个事务管理器
  @Transactional(value="txManager1")
  @Override
  public void send() {
    System.out.println(">>>>>>>>Dev Send()<<<<<<<<\
    send2;
  }
  @Transactional
  public void send2() {
    System.out.println(">>>>>>>>Dev Send"2()<<<<<<<<");
  }
}

隔離レベル

public enum Isolation {
  DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
  READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
  READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
  REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
  SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
  private final int value;
  Isolation(int value) { this.value = value; }
  public int value() { return this.value; }
}
  1. DEFAULT :これはデフォルト値であり、基本データベースのデフォルト隔離レベルを使用することを示します。多くのデータベースでは、通常この値は:READ_COMMITTED です。
  2. READ_UNCOMMITTED :この隔離レベルは、トランザクションが他のトランザクションが修正したがまだコミットしていないデータを読めることを示します。このレベルでは汚読、重複読み取りを防ぐことができません、したがってこの隔離レベルは非常に少ない場合にのみ使用されます。
  3. READ_COMMITTED :この隔離レベルは、トランザクションが他のトランザクションが既にコミットしたデータのみを読めることを示します。このレベルでは汚読を防ぐことができます、これはほとんどの状況での推奨値です。
  4. REPEATABLE_READ :この隔離レベルは、トランザクションの間に何度も同じクエリを実行できることを示し、毎回同じレコードが返されます。このクエリに新しいデータが追加された場合でも、これらの追加レコードは無視されます。このレベルでは汚読、重複読み取りを防ぐことができます。
  5. SERIALIZABLE :すべてのトランザクションは順次個別に実行され、トランザクション間に干渉が完全に不可能になるため、このレベルでは汚読、重複読み取り、幻読を防ぐことができますが、これによりプログラムのパフォーマンスが大幅に低下します。通常はこのレベルは使用されません。

指定方法:isolation属性を使用して設定すること、例えば:

@Transactional(isolation = Isolation.DEFAULT)

伝播行為

現在のトランザクションの開始前にトランザクションのコンテキストが存在する場合、トランザクションメソッドの実行行為を指定するためのいくつかのオプションがあります。

org.springframework.transaction.annotation.Propagationエンムリストクラスで定義されていることができます。6個を示すエンумы値:

public enum Propagation {
  REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
  SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
  MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
  REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
  NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
  NEVER(TransactionDefinition.PROPAGATION_NEVER),
  NESTED(TransactionDefinition.PROPAGATION_NESTED);
  private final int value;
  Propagation(int value) { this.value = value; }
  public int value() { return this.value; }
}

REQUIRED :現在のトランザクションが存在する場合、そのトランザクションに参加;現在のトランザクションが存在しない場合、新しいトランザクションを作成。デフォルト値。

SUPPORTS :現在のトランザクションが存在する場合、そのトランザクションに参加;現在のトランザクションが存在しない場合、トランザクション非処理モードで続行。

MANDATORY :現在のトランザクションが存在する場合、そのトランザクションに参加;現在のトランザクションが存在しない場合、例外をスロー。(強制的にトランザクションに含めます)

REQUIRES_NEW :新しいトランザクションを作成;現在のトランザクションが存在する場合、現在のトランザクションを一時停止。(ログ出力常用、前回のロールバックであっても、このトランザクションは実行され、エラーデータを記録します)

NOT_SUPPORTED :トランザクション非処理モードで実行;現在のトランザクションが存在する場合、現在のトランザクションを一時停止。

NEVER :トランザクション非処理モードで実行;現在のトランザクションが存在する場合、例外をスロー。

NESTED :現在のトランザクションが存在する場合、現在のトランザクションのネストトランザクションとして実行する;現在のトランザクションが存在しない場合、この値はREQUIREDに等しい。

指定されたメソッド:propagation属性を使用して設定することで、例えば:

@Transactional(propagation = Propagation.REQUIRED)

ロールバックされない状況

未捕獲のRuntimeExceptionが発生した場合にのみロールバックが行われます。

catchで投げられた例外が発生すると、二度の挿入が成功します。

@Override
  @Transactional
  public void insertandinsert(Staff staff) {
    staffDao.insert(staff);
    try {
      int i = 1 / 0;
    }
      e.printStackTrace();
    }
    staffDao.insert(staff);
  }

service層のメソッドのcatch文にTransactionAspectSupport.currentTransactionStatus().setRollbackOnly();文を追加し、手動でロールバックを行うとデータが挿入されません。

@Override
  @Transactional
  public void insertandinsert(Staff staff) throws Exception {
    try {
      staffDao.insert(staff);
      int i=1/0;
      staffDao.insert(staff);
    }
      TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
  }

これで本文のすべての内容が終わりました。皆様の学習に役立つことを願っています。また、呐喊教程を多くのサポートをお願いします。

声明:本文の内容はインターネットから取得しており、著作権者に帰属します。インターネットユーザーにより自発的に貢献し、自己でアップロードされています。本サイトは所有権を有しておらず、人工的な編集は行われていません。著作権侵害が疑われる内容を見つけた場合は、以下のメールアドレスまでご連絡ください:notice#oldtoolbag.com(メールを送信する際には、#を@に変更してください。報告を行い、関連する証拠を提供してください。一旦確認がとれましたら、本サイトは即座に侵害される可能性のある内容を削除します。)

おすすめ