15

クエリ自体ではなく、PreparedStatement がある場合に SQL (JDBC) エラーをログに記録することは、常に面倒なことの 1 つです。

あなたはいつも次のようなメッセージで終わります:

2008-10-20 09:19:48,114 ERROR LoggingQueueConsumer-52 [Logger.error:168] Error 
executing SQL: [INSERT INTO private_rooms_bans (room_id, name, user_id, msisdn, 
nickname) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE room_id = ?, name = ?, 
user_id = ?, msisdn = ?, nickname = ?]

もちろん、値を取得し、疑問符を実際の値で解析/置換するためのヘルパー メソッドを作成することもできます (この質問の結果が得られない場合は、おそらくそのパスをたどるでしょう)。この問題は他の誰かによって以前に解決されました。また、私のために自動的にそれを行う汎用ログヘルパーがあるかどうか。

いくつかの回答の後に編集:

これまでに提供されたライブラリは、デバッグ用のステートメントをログに記録するのに適しているようです。これは間違いなく便利です。ただし、PreparedStatement 自体 (一部のサブクラスではない) を取得し、エラーが発生するたびにその SQL ステートメントをログに記録する方法を探しています。PreparedStatement の代替実装を使用して運用アプリを展開したくありません。

PreparedStatement の特殊化ではなく、ユーティリティ クラスを探していると思います。

ありがとう!

4

4 に答える 4

6

log4jdbcを試してみましたが、うまくいきました。

セキュリティ上の注意: 2011 年 8 月現在、ログに記録された log4jdbc 準備済みステートメントの結果は、安全に実行できません。これらは分析に使用できますが、決して DBMS にフィードバックしないでください。

logjdbc によって生成されるログの例:

2010/08/12 16:30:56 jdbc.sqlonly org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 8. INSERT INTO A_TABLE (ID_FILE、CODE1、ID_G、ID_SEQUENCE、REF、NAME、BAR ,DRINK_ID,AMOUNT,DESCRIPTION,STATUS,CODE2,REJECT_DESCR,ID_CUST_REJ) VALUES (2,'123',1,'2','aa','awe',null,'0123',4317.95,'Rccc',' 0',null,null,null)

ライブラリのセットアップは非常に簡単です。


HSQLDBを使用した私の構成:

jdbc.url=jdbc:log4jdbc:hsqldb:mem:sample

オラクルの場合:

jdbc.url=jdbc:log4jdbc:oracle:thin:@mybdd:1521:smt
jdbc.driverClass=net.sf.log4jdbc.DriverSpy

logback.xml :

<logger name="jdbc.sqlonly" level="DEBUG"/>

残念ながらMavenリポジトリにはありませんでしたが、それでも便利です。
私が試したことから、あなたが設定した場合

エラーのステートメントのみが表示されますが、このライブラリがパフォーマンスに影響を与えるかどうかはわかりません。

于 2010-08-12T14:49:16.613 に答える
3

P6Spyを使用します。Oracle、Mysql、JNDI、JMX、SpringMavenに対応しています。高度に構成可能。シンプルで低レベルの統合スタックトレースを出力できます。大量の通話のみを印刷できます- 時間のしきい値に基づいています。

于 2015-08-13T20:49:34.307 に答える
3

これはデータベースに大きく依存します。たとえば、一部の JDBC ドライバー (sybase、おそらく ms-sql など) は、サーバー上に一時ストアド プロシージャを作成し、指定された引数を使用してそのプロシージャを呼び出すことによって準備済みステートメントを処理することを理解しています。したがって、完全な SQL が実際にクライアントから渡されることはありません。

その結果、JDBC API は必要な情報を公開しません。ステートメント オブジェクトを内部ドライバー実装にキャストできる場合もありますが、おそらくできない場合があります。appserver はステートメントを独自の実装にラップする可能性があります。

弾丸を噛んで、引数をプレースホルダーSQLに補間する独自のクラスを作成する必要があるかもしれません。設定されたパラメーターを PreparedStatement に問い合わせることができないため、これは厄介です。そのため、ステートメントにパラメーターを渡す前に、それらをヘルパー オブジェクトに記憶する必要があります。

ドライバーの実装オブジェクトをラップするユーティリティ ライブラリの 1 つが、達成しようとしている最も実用的な方法のように思えますが、どちらにしても不快です。

于 2009-06-19T17:01:35.593 に答える
0
  1. MySQL を使用している場合、MySQL コネクタの PreparedStatement.toString()にはバインドされたパラメータが含まれます。ただし、サードパーティの接続プールはこれを壊す可能性があります。

  2. サブクラス PreparedStatement は、パラメーターが追加されたときにクエリ文字列を構築します。コンパイルされたバイナリ形式を使用するため、PreparedStatement から SQL を抽出する方法はありません。

LoggedPreparedStatementは有望に見えますが、試したことはありません。

すべてのクエリをログに記録するプロキシ ドライバーに対するこれらの利点の 1 つは、クエリ文字列をログに記録する前に変更できることです。たとえば、PCI 環境では、カード番号をマスクしたい場合があります。

于 2009-06-19T15:43:16.060 に答える