web-dev-qa-db-ja.com

JDBCの使用時にSQLステートメントのログを有効にする

Eclipse IDEでOracleデータベースに接続して、JDBCプログラムを使用してログを有効にしようとしています。

私はこれを経験しましたSO post JDBCのファイルへのロギング その後、以下を作成しましたJavaプログラムとEclipse IDEからの実行、ただし、JDBCドライバークラスによって生成されたログを表示できませんでした。

import Java.io.File;
import Java.io.FileInputStream;
import Java.io.PrintWriter;
import Java.sql.Connection;
import Java.sql.DriverManager;
import Java.sql.SQLException;
import Java.util.Properties;
import Java.util.logging.LogManager;
import Java.util.logging.Logger;

public class Logging {

    static Logger log = Logger.getLogger(Logging.class.toString());
    static Connection con = null;

    public static void main(String[] args) throws SQLException,
            ClassNotFoundException {
        System.setProperty("Oracle.jdbc.Trace", Boolean.TRUE.toString());
        System.setProperty("Java.util.logging.config.file",
                "OracleLog.properties");
        log.info("Test Message");
        enableLogging(false);
        getConnection();
        closeConnection();
    }

    static private void enableLogging(boolean logDriver) {
        try {
            Oracle.jdbc.driver.OracleLog.setTrace(true);

            // compute the ObjectName
            String loader = Thread.currentThread().getContextClassLoader()
                    .toString().replaceAll("[,=:\"]+", "");
            javax.management.ObjectName name = new javax.management.ObjectName(
                    "com.Oracle.jdbc:type=diagnosability,name=" + loader);

            // get the MBean server
            javax.management.MBeanServer mbs = Java.lang.management.ManagementFactory
                    .getPlatformMBeanServer();

            // find out if logging is enabled or not
            System.out.println("LoggingEnabled = "
                    + mbs.getAttribute(name, "LoggingEnabled"));

            // enable logging
            mbs.setAttribute(name, new javax.management.Attribute(
                    "LoggingEnabled", true));

            File propFile = new File("path/to/properties");
            LogManager logManager = LogManager.getLogManager();
            logManager.readConfiguration(new FileInputStream(propFile));

            if (logDriver) {
                DriverManager.setLogWriter(new PrintWriter(System.err));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException,
            ClassNotFoundException {
        Properties connectionProps = new Properties();
        connectionProps.put("user", "test_app");
        connectionProps.put("password", "test");

        Class.forName("Oracle.jdbc.driver.OracleDriver");
        con = DriverManager.getConnection(
                "jdbc:Oracle:thin:@"+Host_IP+":1521:"+SID,
                connectionProps);
        System.out.println("Connected to database");
        return con;
    }

    public static void closeConnection() throws SQLException {
        if (con != null) {
            con.close();
        }
    }

}

oracleLog.propertiesファイルには以下のコンテンツがあります。

.level=SEVERE
Oracle.jdbc.level=INFO
Oracle.jdbc.handlers=Java.util.logging.ConsoleHandler
Java.util.logging.ConsoleHandler.level=INFO
Java.util.logging.ConsoleHandler.formatter=Java.util.logging.SimpleFormatter

しかし、クラスパスにojdbc6-11.2.0.3.jarを配置してプログラムを実行すると、次のように例外が発生します。

INFO: Test Message
javax.management.InstanceNotFoundException: com.Oracle.jdbc:type=diagnosability,name=Sun.misc.Launcher$AppClassLoader@73d16e93
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.Java:1095)
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.Java:643)
    at com.Sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.Java:678)
    at myjdbc.Logging.enableLogging(Logging.Java:45)
    at myjdbc.Logging.main(Logging.Java:24)
Connected to database

クラスパスにojdbc6_g.jarがある場合、同じ例外が発生します。

JDBCプログラムのロギングを有効にする方法を教えてください。基本的に、内部JDBCコードによって生成されたログが表示されることを期待しています。

更新:ojdbc6dms.jarファイルをクラスパスに配置しました。私のプログラムは以下の例外を与えています:

Nov 28, 2014 9:09:02 PM jdbc.chap2.Logging main
INFO: Test Message
javax.management.InstanceNotFoundException: com.Oracle.jdbc:type=diagnosability,name=Sun.misc.Launcher$AppClassLoader@73d16e93
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.Java:1095)
    at com.Sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.Java:643)
    at com.Sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.Java:678)
    at jdbc.chap2.Logging.enableLogging(Logging.Java:45)
    at jdbc.chap2.Logging.main(Logging.Java:24)
Exception in thread "main" Java.lang.NoClassDefFoundError: Oracle/dms/console/DMSConsole
    at Oracle.jdbc.driver.DMSFactory.<clinit>(DMSFactory.Java:48)
    at Oracle.jdbc.driver.PhysicalConnection.createDMSSensors(PhysicalConnection.Java:2121)
    at Oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.Java:730)
    at Oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.Java:433)
    at Oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.Java:32)
    at Oracle.jdbc.driver.OracleDriver.connect(OracleDriver.Java:608)
    at Java.sql.DriverManager.getConnection(DriverManager.Java:664)
    at Java.sql.DriverManager.getConnection(DriverManager.Java:208)
    at jdbc.chap2.Logging.getConnection(Logging.Java:70)
    at jdbc.chap2.Logging.main(Logging.Java:25)
Caused by: Java.lang.ClassNotFoundException: Oracle.dms.console.DMSConsole
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:372)
    at Java.net.URLClassLoader$1.run(URLClassLoader.Java:361)
    at Java.security.AccessController.doPrivileged(Native Method)
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:360)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:308)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
    ... 10 more
25
learner

Springフレームワークを使用している場合、 datasource-proxy は非常に便利です。基本的にDataSourceをラップして、ロギング動作を追加するだけです。

enter image description here

Java EEを使用している場合、P6spyは適切な代替手段です。

enter image description here

舞台裏では、 p6spyDriverレベルでステートメントインターセプターを提供します。これは、DataSourceがであるため、Java EEアプリケーションにとってはるかに便利です。アプリケーションサーバーによって提供されます。

6
Vlad Mihalcea

2019更新:log4jdbcは2015年以降保守されていません。 p6spy はまだ積極的に保守されているようです。

元の答え

この目的で使用できるSpyフレームワークはたくさんあります。 log4jdbc を確認してください。これはあなたが探しているものです。

機能

  • JDBC 3およびJDBC 4の完全サポート!
  • 簡単に設定できます。ほとんどの場合、ドライバークラス名をnet.sf.log4jdbc.DriverSpyに変更し、「jdbc:log4」を既存のjdbc urlに追加し、ロギングカテゴリを設定するだけで準備完了です。行け!
  • ログ出力では、準備済みステートメントの場合、バインド引数がSQL出力に自動的に挿入されます。これにより、多くの場合、可読性とデバッグが大幅に改善されます。
  • SQLタイミング情報を生成して、SQLステートメントの実行にかかる時間を特定し、実行が遅すぎるステートメントを特定し、このデータを付属のツールで後処理して、アプリケーション内の低速SQLを迅速に特定するためのプロファイリングレポートデータを生成できます。
  • SQL接続番号情報は、接続プールまたはスレッドの問題を識別するのに役立つように生成されます。基礎となるJDBCドライバー、JDK 1.4以上、およびSLF4J 1.xで動作します。
  • ビジネスに優しいApache 2.0ライセンスの下でライセンスされたオープンソースソフトウェア

使用法

  • Log4jdbc jar(JDKバージョンに基づく)をアプリケーションのクラスパスに配置します。
  • 使用するロギングシステムを選択し、log4j、logback、commons logging..etcがサポートされます
  • アプリケーションの構成でJDBCドライバークラスをnet.sf.log4jdbc.DriverSpyに設定します。多くの場合、スパイされている基礎となるドライバーは、追加の構成なしで自動的にロードされます。
  • Jdbc:log4を、使用している通常のjdbc URLの前に追加します。

    たとえば、通常のjdbcのURLがjdbc:derby:// localhost:1527 // db-derby-10.2.2.0-bin/databases/MyDatabaseの場合、jdbc:log4jdbc:derby:// localhost:に変更します。 1527 // db-derby-10.2.2.0-bin/databases/MyDatabase

  • ロガーをセットアップします。

    jdbc.sqlonly:SQLのみをログに記録します。準備されたステートメント内で実行されたSQLは、バインド引数がその位置にバインドされたデータに置き換えられて自動的に表示され、読みやすさが大幅に向上します。 1.0

    jdbc.sqltiming:SQLの実行後の時間の統計を含む、実行後のSQLを記録します。 1.0

    jdbc.audit:ResultSetsを除くすべてのJDBC呼び出しをログに記録します。これは非常に膨大な出力であり、特定のJDBCの問題を追跡しない限り通常は必要ありません。 1.0

    jdbc.resultset:ResultSetオブジェクトへのすべての呼び出しがログに記録されるため、さらに膨大になります。 1.0

    jdbc.connection:接続のオープンイベントとクローズイベント、および開いているすべての接続番号をダンプします。これは、接続リークの問題を見つけるのに非常に役立ちます。

11
Prince

非常に古いトピックですが、まだ言及されていないのは、必要なトレース対応Oracle JDBCドライバーを使用し、JVMプロパティを介してロギングを有効にするだけで、アプリケーションコードの変更を必要としないOracleのソリューションが存在することです起動時に。

オラクル自身がこれを説明しました here 、そして試行錯誤の後、私はそれを動作させました:

  1. トレース対応のojdbc jarファイルをクラスパスに配置します。リンクされたOracleページからの引用:「ログ出力を取得するには、ojdbc5_g.jarやojdbc6_g.jarなどのファイル名に「_g」で示されているデバッグJARファイルを使用する必要があります。」私のOracle 11gインストールが含まれています

  2. リンクされたOracleページの説明に従ってlogging.propertiesファイルを作成し、必要に応じてログレベルを調整します。例:

    .level=SEVERE Oracle.jdbc.level=FINEST Oracle.jdbc.handlers=Java.util.logging.FileHandler Java.util.logging.FileHandler.level=FINEST Java.util.logging.FileHandler.pattern=jdbc.log Java.util.logging.FileHandler.count=1 Java.util.logging.FileHandler.formatter=Java.util.logging.SimpleFormatter

  3. JVMプロパティ「-Doracle.jdbc.Trace = true -Djava.util.logging.config.file = logging.properties」をJDBCアプリケーションのJava起動コマンドに追加します。

JDBCアプリケーションは、必要な情報を含むjdbc.logという名前のファイルを生成するはずです。場合によっては、logging.propertiesファイルへのフルパスを指定する必要があります。

8
Ralph Kirchner

対応するシステムプロパティを設定しようとしましたか?例えば。トレース用:

System.setProperty( "Oracle.jdbc.Trace", Boolean.TRUE.toString() );

https://docs.Oracle.com/cd/B28359_01/Java.111/b31224/diagnose.htm から)

2
jo-