- PR -

PreparedStatementでプリコンパイルされたSQL文を取得したい

投稿者投稿内容
かにかに
会議室デビュー日: 2005/03/23
投稿数: 18
投稿日時: 2005-09-28 11:39
いつも参考にさせていただいています。

件名にもある通りなのですが、以下のようなコード
PreparedStatement stmt = null;
stmt = conn.prepareStatement("SELECT * FROM table_a WHERE col_a = ?");
stmt.setString(1, "XXX");
System.out.println(stmt.toString());

で、プリコンパイルされたSQL文を標準出力に表示させたいのですが、動かしてみると以下のような文字が出力されます。
"org.apache.commons.dbcp.DelegatingPreparedStatement@10ab3f2"

@以降の数字は実行のたびに変化しています。
何かヒントをいただけると非常に助かります。


ちなみに、実行環境は
Windows XP
J2SE 1.4.2_08
Tomcat 4.1.31
Postgres 8.0.3 (postgresql-8.0-310.jdbc3.jar)
となっています。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-09-28 11:49
>@以降の数字は実行のたびに変化しています。
これはそのオブジェクトのハッシュ値です。

P6Spy とかつかえばバインドされた値を覗くことができますよ。
http://www.p6spy.org/
さる
ぬし
会議室デビュー日: 2005/07/14
投稿数: 276
お住まい・勤務地: 実家戻ったw
投稿日時: 2005-09-28 11:50
プリコンパイルされたSQLって?の所に設定した値が実際に入ってる状態のSQLですっけ?

stmt = conn.prepareStatement("SELECT * FROM table_a WHERE col_a = ?");
stmt.setString(1, "XXX");

SELECT * FROM table_a WHERE col_a = 'XXX'

確かJDBCを弄くらないと出来なかったような・・・
SQL文とSQL文に設定する文字列をそれぞれ出力するじゃ駄目なんですか。
かにかに
会議室デビュー日: 2005/03/23
投稿数: 18
投稿日時: 2005-09-28 12:00
インギ 様
さる 様

すばやいレスポンス、ありがとうございます。
プリコンパイルされたSQLは、プログラムからは簡単に手に入らないのですね。

何がしたかったかというと、仮に INSERT 文などでエラーが発生した場合、エラー原因となった SQL 文を Log4j 等を使用してログに書き出したかったのです。

P6Spyとは、JDBCのやり取りの様子を取得するツールでしょうか。
これから少し調べてみたいと思います。
masa
大ベテラン
会議室デビュー日: 2005/05/11
投稿数: 108
投稿日時: 2005-09-28 12:00
こんにちは。

引用:

かにかにさんの書き込み (2005-09-28 11:39) より:
"org.apache.commons.dbcp.DelegatingPreparedStatement@10ab3f2"



DelegatingPreparedStatementのtoString()が内部に保持する
PreparedStatementのtoString()を呼び出した結果を返してくれていない
ことが原因かと思います。

試していませんが、Javadocを読む限り、stmt.getDelegate().toString()
でうまくいきそうな気がします。
ただしPostgreSQL限定の機能なので、
お薦めはインギさんが示してくれたP6Spyの使用ですね。
かにかに
会議室デビュー日: 2005/03/23
投稿数: 18
投稿日時: 2005-09-28 13:42
masa 様

わざわざ調べて下さってありがとうございます。
早速、以下のようにコードを変更して実行して見ましたが、残念ながら同じ結果になってしまいました。


PreparedStatement stmt = null;
stmt = conn.prepareStatement("SELECT * FROM table_a WHERE col_a = ?");
stmt.setString(1, "XXX");

/* 追加 */
DelegatingConnection dconn = new DelegatingConnection(conn);
DelegatingPreparedStatement dstmt = new DelegatingPreparedStatement(dconn, stmt);

/* 表示 */
System.out.println(dstmt.getDelegate().toString());
System.out.println(dstmt.toString());
System.out.println(stmt.toString());


以上の3つの println 文で、以下のようにまったく同じ内容が3行表示されました。
"org.apache.commons.dbcp.DelegatingPreparedStatement@1ca029b"
"org.apache.commons.dbcp.DelegatingPreparedStatement@1ca029b"
"org.apache.commons.dbcp.DelegatingPreparedStatement@1ca029b"


みなさんがご指摘されるとおり、P6Spy を使用しなければならないでしょうかね〜
masa
大ベテラン
会議室デビュー日: 2005/05/11
投稿数: 108
投稿日時: 2005-09-28 14:02
こんにちは。

引用:

早速、以下のようにコードを変更して実行して見ましたが、残念ながら同じ結果になってしまいました。

PreparedStatement stmt = null;
stmt = conn.prepareStatement("SELECT * FROM table_a WHERE col_a = ?");
stmt.setString(1, "XXX");

/* 追加 */
DelegatingConnection dconn = new DelegatingConnection(conn);
DelegatingPreparedStatement dstmt = new DelegatingPreparedStatement(dconn, stmt);


ん?
コード:
PreparedStatement stmt = null; 
stmt = conn.prepareStatement("SELECT * FROM table_a WHERE col_a = ?"); 
stmt.setString(1, "XXX"); 
System.out.println(((DelegatingPreparedStatement)stmt).getDelegate().toString()); 


じゃないでしょうか?
そのコードだと、
PostgreSQL JDBCドライバの PreparedStatementをラップした、(#1)
DelegatingPreparedStatementをラップした、(#2)
DelegatingPreparedStatementオブジェクト(#3)
から#2を取り出すことになってしまいます。
#1のPreparedStatementが取り出せれば、toString()により期待する
結果が返ってくるはずです。

ただ、P6Spy の使用をお薦めすることに変わりはありませんけれど^^
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-09-28 14:06
P6Spy、英語のサイトになってしまいますが使用は至って簡単です。
英語が苦手でもものの10分もあれば設定できると思いますのでえいやっ、とがんばってください。
クラスパスに通して、JDBCURLをちょこっと変える程度です。
きっとステキな世界が待っています。

スキルアップ/キャリアアップ(JOB@IT)