1.springmvc、MyBatisの、関連のlogback統合
1.春-AOPの使用は、自動化されたログを達成します
依存関係の1.1を追加します(春-AOP、AspectJの)
<スパンのスタイル= "空白:事前に"> </ span>の<依存>
<スパンのスタイル= "空白:事前に"> </ span>の<groupIdを> org.springframework </ groupIdを>
<たartifactId> spring- AOP </たartifactId>
<バージョン> $ {spring.version} </バージョン>
</依存>
<依存性>
<のgroupId> org.aspectj </のgroupId>
<たartifactId> aspectjrt </たartifactId>
<バージョン> 1.5.4 < /バージョン>
</依存>
<依存性>
<のgroupId> org.aspectj </のgroupId>
<たartifactId> aspectjweaver </たartifactId>
<バージョン> 1.8.9 </バージョン>
</依存>
1.2スプリングmvc.xml添加配置
<スパンのスタイル= "空白:事前に"> </ span>を<AOP:AspectJの-自動プロキシプロキシ・ターゲット・クラス= "真" />
この構成は、自動的に生成されたプロキシで、プロキシターゲットクラス=「true」がプロキシ実装クラスを生成するように構成されている薬剤がインターフェイスに追加された場合、これは生成することができます
1.3 Configurationセクション
@Component
@Aspect
パブリッククラスLogAspect {
プライベートログログ= LogFactory.getLog(LogAspect.class)。
@Pointcut( "実行(* com.jiechengkeji.manager .. *(..))")
公共ボイド態様(){
}
@Around( "態様()")
の周りに公衆オブジェクト(ProceedingJoinPoint点){
長い開始=システム.currentTimeMillis()。
。文字列UUID = UUID.randomUUID()のtoString(); //由于开始记录和结束记录会错开、用UUIDの进行配对
= String.Formatの( "%sの前に文字列%S() - ARGS:%S(。 %のS)」、
point.getTarget()のgetClass()。getSimpleName()、
MethodSignature.class.cast(point.getSignature())。getMethod()メソッド。のgetName()、
Arrays.toString(point.getArgs()) 、
UUID)。
log.info(前)。
オブジェクトの結果= NULL;
{試みる
結果= point.proceedを();
}キャッチ(ThrowableをE){
log.error(E);
}
文字列= String.Formatの(後に"%S%() -戻り値:%S TIME:%sのMS(%sの)"、
。。point.getTarget()のgetClass()getSimpleName()、
MethodSignature.class .cast(point.getSignature())getMethod()メソッドのgetName()、。。
結果
のSystem.currentTimeMillis() -開始、
UUID)。
log.info(後)。
結果を返します。
}
}
基本的にはコードを見て何も言うことは理解することができなくなり、@Componentコメントを追加することを忘れないでください。私が考えたとコントローラ@、@サービスが@Componentコメントとして含まれている前に、私は、ない長い時間のための調査を考えていませんでした。
1.4設定logback.xml
<! -アペンダのAOPの日記- >
<アペンダ名= "AOP"クラス= "ch.qos.logback.core.rolling.RollingFileAppender">
<FileNamePattern> $ {log.base} / {$ log.methodModuleName 。}%がd {YYYY-MMは -DD}%i.log </ FileNamePattern> <! - ノートがあれば、ログは、パス{$のlog.max.size}を保存する時間を超えていない設定
のWeb項目であるTomcatの中に保存されていますbinディレクトリ- >
<! - 、ログファイルをロール最初に指定されたファイルへのロギング、条件が一致した場合、他のファイルへのロギング。- >
<rollingPolicyクラス= "ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern> log.base} {$ / $ D {%} {log.methodModuleName MM-DD-YYYY}%I .. log.zip
</ FileNamePattern>
<! -出力ログファイル(ファイル出力ファイルサイズの戦略は、ファイルのバックアップの指定されたサイズを超えて) - >
<timeBasedFileNamingAndTriggeringPolicyの
クラス= "ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
</ timeBasedFileNamingAndTriggeringPolicy>
</ rollingPolicy>
<! -ログファイル形式の出力- >
<レイアウトクラス= "ch.qos.logback.classic.PatternLayout">
<パターン>%{DATEのHH:MM:SS} [ -5level%] MSG%N-%</パターン>
</レイアウト>
</アペンダ>
<スパンのスタイル= "空白:事前に"> </ span>を<ロガー名= "com.jiechengkeji.manager.aop.LogAspect"加法= "偽">
<スパンのスタイル= "空白:事前に"> < / span>の<レベル値= "INFO" />
<スパンのスタイル= "空白:事前に"> </ span>の<アペンダ-REF REF = "AOP" />
<スパンのスタイル= "空白:事前に" > </ span>を</ロガー>
2. MyBatisの統合の
調整のconfig.xml MyBatisの2.1
<設定>
<設定名= "logPrefix"値= "DAO。" /> <! - DAO。是ロガー的名不可省略が- 。>
<設定名= "cacheEnabled"値= "偽" />
<設定名= "defaultExecutorType"値= "REUSE" />
<設定名= "logImpl"値= "COMMONS_LOGGING" />
</設定>
2.2调整logback.xml
<ロガー名= "DAO"レベル= "DEBUG">
<! - daoFILEアペンダが実際に定義されて- >
<アペンダ= REF-REF "AOP" />
</ロガー>
3.効果
ポイントカット@ 1.(「実行(* com.jiechengkeji.manager .. *(..))」) で定義された印刷ログの前に実行される各エントリポイントの後に実行され
、プリント2.mybatis AOPアペンダへログ情報指定されたファイル
の例:
</ PRE> 13時12分35秒[INFO] CityService.getCityNameById() - ARGS:[ - 1](48ded28b-2773-4846-897e-ef14beee273b)13時12分35秒[DEBUG] OOO接続を使用して[ProxyConnection [ PooledConnection [com.mysql.jdbc.JDBC4Connection@386f61ed]]]午前13時12分35秒[DEBUG] ==>準備:dy_cityから選択名前をどこID =?; 午後1時12分35秒[DEBUG] ==>パラメータ:-1(整数)午後1時12分35秒[デバッグ] <==合計:013:12:35 [INFO] CityService.getCityNameById() - 戻り値:NULL TIME :8つのMS(48ded28b-2773-4846-897e-ef14beee273b)13時12分35秒[INFO] LoginController.doLogin() - 戻り値:com.jiechengkeji.manager.util.AsyncResult@23b16363時間:339ミリ秒(15ab451d-fa2e -42e1-ADBE-54e106d77705)<P> </ P> <divのスタイル= "トップ:1283px"> <前の名前= "コード" クラス= "HTML"> @Pointcut(「実行(* com.jiechengkeji.manager。 。*(..)) ")
----------------
免責事項:この記事は、元の記事のCSDNブロガー「スティーブン速度」で、CC 4.0 BY-SAの著作権契約、複製、オリジナルのソースとのリンクを添付してくださいに従ってくださいこの文。
オリジナルリンク:https://blog.csdn.net/winnerwxc/article/details/51612493
なぜトランザクションをコミットすることができます2.SqlSession
タイトルに示されているように、この小さな章ではSQLSESSIONが原因のものの提出をコミットする理由について説明します
彼は、引数なしでコミットする彼の方法を見つけるために、(Ctrlキー+ H)DefaultSqlSessionクラスを見つけるために、彼のクラスを達成するためのインタフェース、ですが、またなぜなら、我々は呼んでいる彼のノンパラメトリック法のSQLSESSION commit()メソッドではまず見て、見下します
公共のボイド(コミット){ this.commit(偽); } 公共ボイドが{(ブール力を)犯します {試します this.executor.commit(this.isCommitOrRollbackRequired(力))。 this.dirty = falseは、 }キャッチ(例外var6){ ExceptionFactory.wrapException( "エラーコミットトランザクションの原因となります。:" + var6、var6)投げます。 } 最後に { ErrorContext.instance()リセット()。 } }
それから参照してください?彼は力がfalseで、我々はレコードを更新している、彼の方法は、以下のパラメータを持っていると呼ばれ、パラメータを渡します
アクチュエータ下記偽汚れ提出となり、データを説明することは汚れていません
executor.commit(XXX)アクチュエータ提出し、我々は偽の値を渡すために注意を払う、法の内部を見て、内部のメソッド呼び出しでは、メソッドのパラメータをコミットし、戻り値を取得し、そのメソッドの内部を見ます
プライベートブールisCommitOrRollbackRequired(ブール力){ 返す!this.autoCommit && this.dirty || 力; }
この方法は、ビット無知一見、真実を伝えるために、しかし、あなたが知っている!&& ||使用の優先順位を、あなたは!&&> ||>アウト計算trueに戻って結果を返すことができます
上記this.dirty trueに変更方法を更新する底への追加や削除が呼び出され、前記背面上にあります
彼はfalseに変更したときに上記のAutoCommitが、初期の基礎となるののOpenSessionメソッドをSQLSESSIONを作成します
次に、上記上記executor.commitを見て(XXX)メソッドは,,彼は彼のクラスの実装クラスBaseExecutorをコミットブールパラメータを持つメソッドを見つけるために、エグゼキュータアクチュエータインタフェースであります
公共ボイド(ブール値が必要)コミット、SQLExceptionをスローします{ IF(this.closed){ (「トランザクションが既に閉じられているコミットすることはできません」)新しいExecutorExceptionを投げます。 }他{ this.clearLocalCache(); this.flushStatements(); もし必要なら) { this.transaction.commit(); } } }
flushStatementsは、パラメータを更新し、キャッシュをクリアすることがあり、いくつかの不要な注意がありますが、口の簡単な言及、clearLocalCache()
コードの彼の次の行がtransaction.commit()、オハイオ州、トランザクション英語名が呼ばれる事があるので、関心の最終レベルに必要なパラメータが渡された場合、すでに説明しているためには、真であります
文の終わり:session.commit()最終的に物事を提出する予定で、this.transaction.commit()
挿入を3.mybatis、基礎となる実装方法を削除
insertメソッドに見て最初のポイント
内部参照するには、マウスの左ボタンとCtrlキープラスポイント
ディスカバリーは具体化しなかった、インタフェースSQLSESSIONの方法ですが、リヒターによる置換原則の考え方は、彼がインタフェースの実装クラスを受けるので、彼はクラスDefaultSqlSession(アイデアのショートカットCTRL + H)を達成するために見ています
CTRL + Fで行ったのインサートを探すには、オーバーロードを構成insertメソッドの詳細を参照することができますが、その実装は、このメソッドを呼び出します
公共int型の挿入(文字列の声明){ this.insert(声明、(オブジェクト)はnull)を返します。 } 公共int型の挿入(文字列のステートメント、オブジェクトのパラメータ){ this.update(ステートメント、パラメータ)を返します。 }
その方法の上に実際にupdateメソッドを呼び出して、次の方法を挿入し、次のメソッドを呼び出します
deleteメソッドで再び見て、
彼と同様の挿入、SQLSESSION道のインターフェースなので、それはまだ彼の実装クラスDefalutSqlSessionを探しています
deleteメソッドの後に、それに探し続けて
公共int型削除(文字列の声明){ this.update(声明、(オブジェクト)はnull)を返します。 } 公共int型削除(文字列のステートメント、オブジェクトのパラメータ){ this.update(ステートメント、パラメータ)を返します。 }
我々は、彼がupdateメソッドを呼び出して見ることができるので、それは好奇心を誘発し、そこに2つの引数を持つ更新方法は何ですか?なぜあなたはそれを呼び出すしていますか?
更新方法を見てください
公共int型の更新(文字列のステートメント、オブジェクトのパラメータ){ int型のVAR4。 {試します this.dirty =はtrue。 MappedStatement電子= this.configuration.getMappedStatement(声明)。 VAR4 = this.executor.update(E、this.wrapCollection(パラメータ))。 }キャッチ(例外がvar8){ ExceptionFactory.wrapException( "更新エラーデータベースを原因。:" +がvar8、がvar8)投げます。 } 最後に { ErrorContext.instance()リセット()。 } VAR4を返します。 }
ここでは簡単な方法です、
1)汚れた=真;彼はここで変更される理由は、メモリやデータベースの不整合のデータは、おそらく我々は必要性への追加や削除は手動でトランザクションをコミットする理由について話すべきであることを意味し、ダーティデータの代表となっている(session.commit())と
なぜ物事のsession.close原因のロールバック、次のいくつかの章には、滑走分析についての簡単なブログを持っていること
2)これは私がいくつかの情報を見つけるMappedStatementが、これは、単に間違っているならば、それは特定のSQL MyBatisの構成を取得するにする必要があり、私はそれを指摘して助けてください、と言っているかを理解するためにBaiduの検索に語ったことはありません
3)VAR4アクチュエータはSQLで行われ、戻り値を受信し、更新からの戻り値がintであり、そしてVAR4であり、彼が影響を受けた行の数を返す必要があることを推測することができます
4)ErrorContextは、リセット、リセットがリセットされ、インスタンスは静的方法で彼の元の意味の一例であり、間違ったコンテキストの文字通りの意味から理解、またはオブジェクトのインスタンスを作成ErrorContextインスタンスを取得し、バック単一の実施形態の書き込みを返します
初期化手段