どのような状況の下で春@Transactionalアノテーションは失敗し、なぜでしょうか?

出典:   https://www.cnblogs.com/hunrry/p/9183209.html

     https://www.cnblogs.com/protected/p/6652188.html

 

 

ここ数日で、私は@Transactional注釈トランザクションを使用するプロジェクトの発見後、実際にロールバックされていない例外をスローします。その後、最終的に私は、その理由を見つけました。 
あなたもこのようなケースを持っている場合は、以下のトラブルシューティングを開始することができます。

まず、特性

トランザクションのアノテーション@Transactionalそれの特性で見てみましょう、あなたはトラブルシューティングをより良くすることができます

1は、サービスクラスラベル(一般的にインターフェイスにはお勧めしませんが)@Transactionalを追加し、クラス全体が春のトランザクション管理に組み込むことができ、各ビジネスメソッドの実行場合、トランザクションを開いたが、同じ管理とこれらの取引になります。

2は、@トランザクション注釈のみに適用することができ、パブリック メソッドの可視性に。プライベートまたはパッケージの可視性メソッドprotected、で使用される場合は、エラーではないが、トランザクションの設定は動作しません。

3.デフォルトで、春にはなり未確認の異常のトランザクションのロールバックは、それがチェックされている場合は、例外がロールバックされます。 
それスパイシーは未チェック例外があるか、例外をどのようにチェックされます

エラーのJava生まれ又は(例えばヌルポインタと、1/0)のRuntimeExceptionを送信するどのような等にIOException、TimeoutExceptionとしてのjava.lang.Exception異常にまとめてチェック例外から継承された他の異常チェック例外、、と呼ばれ

  スパイシーし、それはっきり:あなたはNULLポインタ例外が発生するようなは、ロールバックされたコードを記述し、読み取りと書き込みのファイル、ネットワークの問題は、春をロールバックアップすることはできません。それから私は、どのようにこのことを覚えておくことをお教えしましょう多くの学生が簡単に混乱しているため、一部のIOException私たちのコンパイラが検出することが可能であるとき、あなたはコードを書く、彼はあなたが検出不可能で死ぬためにヌル・ポインタとしてコードを書く、チェック例外と呼ばれていると言わので、未チェックの例外と呼ばれます。これはそれのいくつかを覚えておくことは容易ではありません

4、読み取り専用トランザクション: 
(trueに伝播= Propagation.NOT_SUPPORTED、読み取り専用=)@Transactionalは、 
読み取り専用フラグをアプリケーションがトランザクションを開始し、あるいは設定が無視される場合にのみ。 
データベースが(データベースおよびトランザクション分離レベルのタイプに特異的に関連して)読み出され、ロックされた共有ため、トランザクションが、スレッドのオーバーヘッドを増加させる開始。典型的には、読み取り専用トランザクションおよび追加のシステムオーバーヘッドを設定しなくても、データを読み出します。

2:トランザクション伝播モード

様々なトランザクション伝播モードを列挙伝播は、一部の下に記載されています:

  • 1、REQUIRED(デフォルトモード):ビジネスメソッドは、コンテナ内で実行する必要があります。メソッドが実行されている場合は、すでにトランザクションでは、このトランザクションに追加するか、新しい独自の事務を作成します。

  • 2、NOT_SUPPORTED:ステートメントメソッドは、トランザクションを必要としません。メソッドがトランザクションに関連付けられていない場合、コンテナはメソッドがトランザクション内で呼び出された場合、トランザクションはコールの終了後に、元のトランザクションは実行を再開します、中断され、彼の事務を開きません。

  • 3、RequiresNewを:トランザクションがあるかどうか、メソッドの合流は、自分自身のための新規事業を立ち上げました。この方法は、すでにトランザクションで実行されている場合は、元のトランザクション・サスペンション、新しいトランザクションが作成されます。

  • MANDATORY 4、この方法は、既存のトランザクションの実行にすることができ、ビジネスの方法は、自分の業務を開始することはできません。トランザクション環境なしで呼び出された場合、コンテナは例外をスローします。

  • 図5は、サポートしています。この方法は、トランザクションの範囲内で呼び出され、この方法は、トランザクションの一部となります。この方法は、トランザクションのスコープ外で呼び出された場合、メソッドはトランザクション環境なしで実行されます。

  • 6は、NEVER:このメソッドは、トランザクションの範囲内で実行されないことはできません。あなたは例外をスローした場合。唯一の方法は、任意のトランザクションに関連付けられていない、通常のを実行します。

  • 7、NESTED:アクティブがあるトランザクション場合、ネストされたトランザクションで実行されます。アクティブなトランザクションがない場合は、プレスREQUIREDプロパティを実行します。これは、ポイントはロールバックすることができ、省トランザクションが複数あり、別のトランザクションを使用しています。ロールバック内政は対外には影響しません。DataSourceTransactionManagerトランザクションマネージャのだけが発症。

 

2:トランザクションの注釈が背中を丸めていません解決するために、

あなたのメソッドが公開されていないチェック1

2、あなたの例外がチェック例外ではありません入力し 
、私は異常確認したい場合も、上記で述べたコメントに、例外の種類を行うにはどのようにロールバックしたいです

@Transactional(rollbackFor = Exception.class) 

同様のnorollbackForがありますが、カスタムはバック異常なロールはありません

それは、MySQL、それはMyISAMテーブルの場合、テーブルは、InnoDBのような、エンジンのサポートサービスを使用することに注意している場合3は、データベースエンジンは、トランザクションをサポートするために、トランザクションは動作しません。

注釈の解析を開くかどうか4、

<TX:注釈駆動型トランザクション・マネージャ=「のTransactionManager」プロキシ・ターゲット・クラス=「真」/>

5、あなたにこのパッケージをスキャンするかどうか春には、以下のものを次のパッケージorg.testスキャンされ

<コンテキスト:コンポーネント・スキャンベースパッケージ=「org.test」> </コンテキスト:コンポーネント・スキャン>

図6は、同じチェックがクラスメソッドの呼び出し(同じクラスのメソッド呼び出しとして、方法b)ではありません 
あなたが住んでキャッチされていない異常で、7

 


 

質問:なぜ公共の修飾方法は、総務ノートが失敗表示されないのですか?

  サービスが部屋の中に注入されていないため、これらの日、私の同僚は問題がある、カット方向Aopとコントローラは、リクエストログを再生し、チューニングサービス層のメソッドの結果は、nullポインタエラーを報告しました。使用 @Autowired して @Resource ノートが付属していませんが注入されます。線でコード行をチェックし、エラーはあなたが実行できる場所を確認、その後、メソッドを削除する唯一の方法を発見した、とコントローラがプライベートメソッドプライベートタイプであるため、ことがわかっています。その後、公衆にそれを変更しました。

一見ではないプライベートメソッドインターセプト? 
何度も試みましたが失敗しました、それがああではありませんか? 

底がAOP薬であるので、私は、一瞬考えた 
プライベートメソッドがインターフェイスに存在していなければなりません、それは傍受されることはありません、JDKがプロキシインタフェースである。 
CGLIBは、サブクラスで、プライベートメソッドはまだサブクラスに表示されません。そして傍受することはできません。 

私は直接呼ばれる内部クラスメソッドではないけど、プロキシ経由での独自のインスタンスを維持するために 

実行(* test.aop.ServiceAを。*(..  ))
パブリック クラスSERVICEA {   
  
    プライベートサービスAの自己;  
  
    公共 ボイドsetSelf(サービスAの自己){  
         この .self = 自己。  
    }   
  
    パブリック文字列methodA(文字列str){   
        するSystem.out.println( "methodA:引数=" + STR)。  
        self.methodB( "B" );  
        リターン "12345" + STR。  
    }   
  
    プライベート文字methodB(文字列str){   
        するSystem.out.println( "methodB:引数=" + STR)。  
        self.methodC( "C" );  
        リターン"12345" + STR。  
    }   
  
    パブリック文字列methodC(文字列str){   
        するSystem.out.println( "methodC:引数=" + STR)。  
        リターン "12345" + STR。  
    }   
}

それはそのようなことではないでしょうか? 
しかし、stackoverflowの上、いくつかの発言ファインワークスITが 
http://stackoverflow.com/questions/4402009/aspectj-and-catching-private-or-inner-methods 

実行(パブリックtest.aop.ServiceA *。*(..)) 
あなたが書き込みしませ許可を行う場合は、公共の保護されたパッケージの方法を傍受することが可能で奇妙な現象、実行があり 
ますが、公開を書いた場合、それが唯一の公共の方法インターセプトこれは、問題ではないだろう 
書き込みが保護された場合、彼は何だったの行わない、でも、保護された方法が傍受されていません。

 

分析

カバーできないサブクラスとして遮られるべきではないスプリング(のみノックダウンパブリック/プロテクテッド/パッケージ)で純粋スプリングAOPを使用してプライベート方法は、パケット・レベルが傍受理由であることができるである場合には、同じパッケージ内のサブクラスとスーパーカバーすることができます。 

エージェントCGLIB、実行(*(..)の場合に ) 公開/保護/パッケージレベルの方法(可能な薬剤である、すなわちメソッド)をインターセプトすることができます。 

プライベート 静的 ブールisOverridable(方法メソッド、クラスtargetClass){  
         場合(Modifier.isPrivate(method.getModifiers())){  
             戻り 
        }   
        であれば(Modifier.isPublic(method.getModifiers())|| Modifier.isProtected(method.getModifiers())){  
             戻り 
        }   
        を返す。getPackageNameは(method.getDeclaringClass())に等しい(getPackageName(targetClass))。  
    }

あなたはインターセプトプライベートネイティブAspectJのコンパイル時/実行時の織りに使用することができますメソッドを実装します。 


引用文
書き込みが保護された場合は、彼は何もしないだろう、でも保護​​された方法は、傍受ではありません。これはすべきではありません


基本的な理由を理解するための分析: 

(org.springframework.aop.support.AopUtils)を次のようにアプリケーションコードが増強されるかどうかを決定しました。

パブリック 静的 ブール canApply(ポイントカットPC、クラスtargetClass、ブールhasIntroductions){  
     場合(!。pc.getClassFilter()マッチ(targetClass)){  
         リターン はfalse ;  
    }   
  
    MethodMatcher methodMatcher = pc.getMethodMatcher()。  
    IntroductionAwareMethodMatcher introductionAwareMethodMatcher = nullをもし(methodMatcher instanceofのIntroductionAwareMethodMatcher){   
        introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher)methodMatcher。  
    }  
  
    設定クラス = 新しいHashSetの(ClassUtils.getAllInterfacesForClassAsSet(targetClass));  
    classes.add(targetClass)。  
    ため(イテレータが= ; it.hasNext(); classes.iterator()){   
        クラスclazz = (クラス)it.next();  
        方法[]メソッド = clazz.getMethods()。  
        INT ; J <methods.length、J = 0 J ++ ){  
             もし!((introductionAwareMethodMatcher = NULL &&   
                    introductionAwareMethodMatcher.matches(方法[J]、targetClass、hasIntroductions)) ||  
                    methodMatcher.matches(方法[J]、targetClass)){   
                戻り 
            }   
        }   
    }   
  
    を返す 
}  

ここで方法[]メソッド= clazz.getMethods() ; 公共のみ取得方法。。 

シーン1:実行(* *(..  ))

パブリック クラスImpl2 {   
      
    保護 / パブリック文字列testAop2(){   
        System.out.printlnは( "234" )。  
        返す「1233」
    }   
}  

アクセス修飾子エントリポイントが存在しないので、この公開待機方法のcanApply方法を取得するように、すなわち、いずれであってもよい、すなわち、エージェントが実装されてもよいです。 

シーン2:実行(パブリック* *(  ...))

パブリック クラスImpl2 {   
      
    パブリック文字列testAop2(){   
        System.out.printlnは( "234" )。  
        返す「1233」
    }   
}  

公共傍受ので、ので、このパブリックwaitメソッドのcanApply方法を取得するよう、すなわち、エージェントが実装されてもよいです。 


シーン3:実行(保護* *(  ...))

パブリック クラスImpl2 {   
      
    保護された文字列testAop2(){   
        System.out.printlnは( "234" )。  
        返す「1233」
    }   
}  

前に言った、canApplyメソッドです[]は、メソッド= clazz.getMethods()を覚えておいてください。唯一のパブリックメソッドを取得することができますので、保護されたアクセス修飾子を持つ(*ので、「実行(保護された*場合、一致しません...))「エージェントではありません。 

純粋な春AOP環境の実行中ではない仕事が理由です(* *保護されました(..) )。 

トランザクションの注釈業務@、特殊な状況に注意してください。 

引用文
可視性との@Transactional方法 
トランザクション@注釈が唯一の公共の可視性の方法に適用されなければならないとき、プロキシを使用しました。あなたがプライベートまたはパッケージ可視保護法上の@Transactionalのアノテーションを使用する場合、システムはエラーではありませんが、アノテーション付きメソッドは、トランザクション構成された設定を実行しません。あなたは非パブリックメソッドに注釈を付けることがある場合は、AspectJの使用を参照してください。 

 

おすすめ

転載: www.cnblogs.com/myseries/p/12082254.html