- PR -

jdbcログに関して

1
投稿者投稿内容
ゆう
常連さん
会議室デビュー日: 2001/12/10
投稿数: 33
投稿日時: 2005-07-09 23:29
いつもお世話になっています。
現在以下の環境下でDB(DBサーバ)+Webアプリケーション(APサーバ)を作成しています。
Oracle9i
JDBC Driver:ojdbc.jar
DBサーバ:soralis
APサーバ:soralis

障害発生時の解析のため、WebアプリケーションからDBに対して
送信するSQLのログを出力したいのですが、
PreparedStatement/CallableStatementをそのまま使用しているとバインド変数に実際に
何が設定してあるかを調べるのは「ojdbc_g.jar」を使用しないと無理なのでしょうか?
またoracle側でログを出力することも考えましたが、その場合、Webアプリケーションの
セッションID等が分からないので障害解析の忌みがなくなると思っています。

一般的にこのようにJDBCのログ(バインド変数に何が設定されるか)を出力し、
WebアプリケーションのセッションIDも同時に出力したい場合はどのように実装するものなのか教えてください。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2005-07-10 01:23
ServletAPIとJDBCは全く違うものなので、
ログを一緒にというなら無理な話です。

セッションIDも一緒に出力したいのであれば、
WEBアプリ側で出力すべきでしょう。

オラクルのJDBCドライバの関連のプロキシクラスを作って、
そこでログを出力するって方法もありますね。
コード:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.PreparedStatement;

public class PreparedStatementLogger implements InvocationHandler{

    private String sessionId;
    private PreparedStatement ps;
    
    public PreparedStatementLogger(String sessionId,PreparedStatement ps){
        this.sessionId = sessionId;
        this.ps = ps;
    }
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        StringBuffer buf = new StringBuffer();

        //引数の値を文字列に変換
        for(int i = 0; i < args.length; i++){
            if(i > 0){
                buf.append(",");
            }
            buf.append(args[i]);
        }

        if(buf.length() > 0){
            //実際には適当なロガーで出力
            System.out.println("SessionId = " + sessionId + ":" + buf);
        }
 
        Method m = ps.getClass().getMethod(method.getName(),method.getParameterTypes());
        return m.invoke(proxy,args);
    }

    //ここはサーブレットのメソッドと仮定
    public static void main(String[] args) throws Exception{
        //実際はコネクションから取得
        PreparedStatement ps = null;

        //実際はセッションから取得
        String sessionId = "12345";

        //プロキシの引数を作成
        Class[] interfaces = new Class[]{PreparedStatement.class};
        InvocationHandler handler = new PreparedStatementLogger(sessionId,ps);
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if(loader == null){
            loader = PreparedStatement.class.getClassLoader();
        }

        //プロキシのインスタンスを生成
        PreparedStatement psProxy = (PreparedStatement) Proxy.newProxyInstance(loader,interfaces,handler);

        //PreparedStatementの処理
        psProxy.setString(1,"aaaaa");
        psProxy.setString(2,"aaaaa");
    }
}


これは、PreparedStatementでやってますが、
Connection用のプロキシを作成するって方法もありますね。
1

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