sql >> データベース >  >> RDS >> Oracle

Bがうまくいかない場合は、Aをロールバックします。スプリングブーツ、jdbctemplate

    @Transactional Springのアノテーションは、オブジェクトをプロキシでラップすることで機能します。プロキシは、@Transactionalでアノテーションが付けられたメソッドをラップします。 トランザクションで。そのため、プライベートメソッドは継承できないため、(例のように)プライベートメソッドではアノテーションは機能しません。 =>ラップすることはできません(これは、aspectjで宣言型トランザクションを使用する場合は当てはまりません。その場合、以下のプロキシ関連の警告は適用されません)。

    @Transactionalの基本的な説明は次のとおりです。 春の魔法が効く。

    あなたが書いた:

    class A {
        @Transactional
        public void method() {
        }
    }
    

    しかし、これはBeanを注入したときに実際に得られるものです:

    class ProxiedA extends A {
       private final A a;
    
       public ProxiedA(A a) {
           this.a = a;
       }
    
       @Override
       public void method() {
           try {
               // open transaction ...
               a.method();
               // commit transaction
           } catch (RuntimeException e) {
               // rollback transaction
           } catch (Exception e) {
               // commit transaction
           }
       }
    } 
    

    これには制限があります。 @PostConstructでは機能しません オブジェクトがプロキシされる前に呼び出されるため、メソッド。また、すべてを正しく構成した場合でも、トランザクションはチェックされていないでのみロールバックされます。 デフォルトでは例外。 @Transactional(rollbackFor={CustomCheckedException.class})を使用します チェックされた例外でロールバックが必要な場合。

    私が知っているもう1つの頻繁に遭遇する警告:

    @Transactional 次の例では、b()のように、メソッドを「外部から」呼び出した場合にのみ機能します。 トランザクションにラップされません:

    class X {
       public void a() {
          b();
       }
    
       @Transactional
       public void b() {
       }
    }
    

    @Transactionalも理由です オブジェクトをプロキシすることで機能します。上記の例では、a() X.b()を呼び出します 強化された「スプリングプロキシ」メソッドではありませんb() したがって、トランザクションはありません。回避策として、b()を呼び出す必要があります 別の豆から。

    これらの警告のいずれかに遭遇し、推奨される回避策を使用できない場合(メソッドを非プライベートにするか、b()を呼び出します 別のBeanから)TransactionTemplateを使用できます 宣言型トランザクションの代わりに:

    public class A {
        @Autowired
        TransactionTemplate transactionTemplate;
    
        public void method() {
            transactionTemplate.execute(status -> {
                A();
                B();
                return null;
            });
        }
    
    ...
    } 
    

    更新

    上記の情報を使用して、OPの更新された質問に回答します。

    @Transactional:changes()で注釈を付ける必要があるメソッドはどれですか? databaseChanges()?

    @Transactional(rollbackFor={Exception.class})
    public void changes() throws Exception {
        someLogicBefore();
        databaseChanges();
        someLogicAfter();
    }
    

    changes()を確認してください クラス自体からではなく、コンテキストがインスタンス化された後、Beanの「外部から」と呼ばれます(たとえば、これはafterPropertiesSet()ではありません または@PostConstruct 注釈付きメソッド)。スプリングは、デフォルトでチェックされていない例外に対してのみトランザクションをロールバックすることを理解します(チェックされた例外のrollbackForリストでより具体的にするようにしてください)。



    1. AWSRDSでのMySQLデータベースおよびOracleデータベースでのJDeveloperの使用パート1

    2. SQLでのピボット演算子の理解

    3. MySQL I/O使用率が高いかどうかを確認する方法

    4. WindowsにSQLServerをインストールする方法