简体   繁体   English

使用 JDBC 时如何为 SQL 语句启用日志记录

[英]How to enable logging for SQL statements when using JDBC

I am trying to enable logs using my JDBC program by connecting to Oracle database in eclipse IDE.我正在尝试通过连接到 Eclipse IDE 中的 Oracle 数据库来使用我的 JDBC 程序启用日志。

I have gone through this SO post JDBC logging to file then I have created below java program and running it from my eclipse IDE, but I was not able to see any logs generated by the JDBC driver classes.我已经完成了这个 SO post JDBC logging to file然后我在 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();
        }
    }

}

and I have below content in my OracleLog.properties file:我的 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

But when I run my program by placing ojdbc6-11.2.0.3.jar in classpath then I am getting exception as:但是当我通过在类路径中放置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

If I have ojdbc6_g.jar in classpath then also I am getting same exception.如果我在类路径中有ojdbc6_g.jar ,那么我也会遇到同样的异常。

Please let me know how can I enable logging for my JDBC program?请让我知道如何为我的 JDBC 程序启用日志记录? basically I am expecting to see the logs generated by the internal JDBC code.基本上我希望看​​到内部JDBC代码生成的日志。

Update: Now I placed ojdbc6dms.jar file in classpath, my program is giving below exception:更新:现在我将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

2019 update: log4jdbc has not been maintained since 2015. p6spy still seems to be actively maintained. 2019年更新:log4jdbc从2015年开始就没有维护了, p6spy好像还在积极维护。

Original answer原答案

There are lot of Spy frameworks available for this purpose , please check log4jdbc , I fell this is what you are looking for.有很多间谍框架可用于此目的,请检查log4jdbc ,我认为这就是您正在寻找的。

Features特征

  • Full support for JDBC 3 and JDBC 4!完全支持 JDBC 3 和 JDBC 4!
  • Easy to configure, in most cases all you need to do is change the driver class name to net.sf.log4jdbc.DriverSpy and prepend "jdbc:log4" to your existing jdbc url, set up your logging categories and you're ready to go!易于配置,在大多数情况下,您需要做的就是将驱动程序类名称更改为 net.sf.log4jdbc.DriverSpy 并将“jdbc:log4”添加到您现有的 jdbc url,设置您的日志记录类别,您就可以走!
  • In the logged output, for prepared statements, the bind arguments are automatically inserted into the SQL output.在记录的输出中,对于准备好的语句,绑定参数会自动插入到 SQL 输出中。 This greatly Improves readability and debugging for many cases.这大大提高了许多情况下的可读性和调试。
  • SQL timing information can be generated to help identify how long SQL statements take to run, helping to identify statements that are running too slowly and this data can be post processed with an included tool to produce profiling report data for quickly identifying slow SQL in your application.可以生成 SQL 计时信息来帮助确定 SQL 语句运行需要多长时间,帮助确定运行速度过慢的语句,并且可以使用包含的工具对这些数据进行后处理以生成分析报告数据,以便快速识别应用程序中的慢 SQL .
  • SQL connection number information is generated to help identify connection pooling or threading problems.生成 SQL 连接号信息是为了帮助识别连接池或线程问题。 Works with any underlying JDBC driver, with JDK 1.4 and above, and SLF4J 1.x.适用于任何底层 JDBC 驱动程序、JDK 1.4 及更高版本和 SLF4J 1.x。
  • Open source software, licensed under the business friendly Apache 2.0 license开源软件,在商业友好的 Apache 2.0 许可下获得许可

Usage用法

  • Place the log4jdbc jar (based on the JDK version) into your application's classpath.将 log4jdbc jar(基于 JDK 版本)放入应用程序的类路径中。
  • choose logging system to use, log4j, logback, commons logging..etc are supported选择要使用的日志系统,支持 log4j、logback、commons logging..etc
  • Set your JDBC driver class to net.sf.log4jdbc.DriverSpy in your application's configuration.在应用程序的配置中将 JDBC 驱动程序类设置为 net.sf.log4jdbc.DriverSpy。 The underlying driver that is being spied on in many cases will be loaded automatically without any additional configuration.在许多情况下被监视的底层驱动程序将自动加载,无需任何额外配置。
  • Prepend jdbc:log4 to the normal jdbc url that you are using.将 jdbc:log4 前置到您正在使用的普通 jdbc url。

    For example, if your normal jdbc url is jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase then You would change it to: jdbc:log4jdbc:derby://localhost:1527//db-derby-10.2.2.0-bin/databases/MyDatabase例如,如果您的普通 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

  • Set up your loggers.设置你的记录器。

    jdbc.sqlonly : Logs only SQL. jdbc.sqlonly :仅记录 SQL。 SQL executed within a prepared statement is automatically shown with it's bind arguments replaced with the data bound at that position, for greatly increased readability.在准备好的语句中执行的 SQL 会自动显示,其绑定参数替换为在该位置绑定的数据,以大大提高可读性。 1.0 1.0

    jdbc.sqltiming : Logs the SQL, post-execution, including timing statistics on how long the SQL took to execute. jdbc.sqltiming :记录执行后的 SQL,包括 SQL 执行时间的计时统计信息。 1.0 1.0

    jdbc.audit : Logs ALL JDBC calls except for ResultSets. jdbc.audit :记录除 ResultSet 之外的所有 JDBC 调用。 This is a very voluminous output, and is not normally needed unless tracking down a specific JDBC problem.这是一个非常庞大的输出,通常不需要,除非跟踪特定的 JDBC 问题。 1.0 1.0

    jdbc.resultset : Even more voluminous, because all calls to ResultSet objects are logged. jdbc.resultset :更加庞大,因为所有对 ResultSet 对象的调用都被记录下来。 1.0 1.0

    jdbc.connection : Logs connection open and close events as well as dumping all open connection numbers. jdbc.connection :记录连接打开和关闭事件以及转储所有打开的连接号。 This is very useful for hunting down connection leak problems.这对于查找连接泄漏问题非常有用。

Very old topic, I know, but what has not been mentioned yet is that for Oracle a solution exists which does not require any change in the application code, just by using the required trace-enabled Oracle JDBC driver and enabling the logging through JVM properties at startup.很老的话题,我知道,但还没有提到的是,对于 Oracle,存在一个不需要更改应用程序代码的解决方案,只需使用所需的启用跟踪的 Oracle JDBC 驱动程序并通过 JVM 属性启用日志记录在启动时。

Oracle themselves have described this here , and after some trial and error I got it to work: Oracle 自己在此处对此进行描述,经过一些试验和错误后,我让它工作了:

  1. Place the trace-enabled ojdbc jar file in your classpath.将启用跟踪的 ojdbc jar 文件放在您的类路径中。 Quote from the linked Oracle page: "To get log output, you must use the debug JAR files, which are indicated with a "_g" in the file name, like ojdbc5_g.jar or ojdbc6_g.jar."引用来自链接的 Oracle 页面:“要获取日志输出,您必须使用调试 JAR 文件,这些文件在文件名中以“_g”表示,例如 ojdbc5_g.jar 或 ojdbc6_g.jar。” My Oracle 11g installation contained我的 Oracle 11g 安装包含

  2. Create a logging.properties file as described on the linked Oracle page, and adjust the logging levels to your needs.按照链接的 Oracle 页面中的说明创建 logging.properties 文件,并根据需要调整日志记录级别。 Example:例子:

    .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. Add the JVM properties "-Doracle.jdbc.Trace=true -Djava.util.logging.config.file=logging.properties" to the java startup command for your JDBC application.将 JVM 属性“-Doracle.jdbc.Trace=true -Djava.util.logging.config.file=logging.properties”添加到 JDBC 应用程序的 java 启动命令。

The JDBC application should now produce a file named jdbc.log which should contain the desired information. JDBC 应用程序现在应该生成一个名为 jdbc.log 的文件,其中应该包含所需的信息。 In some cases it can be necessary to specify the full path to the logging.properties file.在某些情况下,可能需要指定 logging.properties 文件的完整路径。

If you are using Spring framework, then the datasource-proxy framework is very convenient.如果你使用的是Spring框架,那么datasource-proxy框架就非常方便了。 You can basically wrap around any DataSource and just add the logging behavior.您基本上可以环绕任何DataSource并添加日志记录行为。

在此处输入图片说明

If you're using Java EE, then P6spy is a good alternative:如果您使用的是 Java EE,那么 P6spy 是一个不错的选择:

在此处输入图片说明

Behind the scenes, p6spy provides the statement interceptor at the Driver level, which is much more convenient for Java EE applications because the DataSource is provided by the application server.在幕后, p6spy提供了Driver级别的语句拦截器,这对于Java EE 应用程序来说更加方便,因为DataSource是由应用程序服务器提供的。

Assuming you're using Log4j , just do this:假设您使用的是Log4j ,请执行以下操作:

Use ojdbc_g as mentioned in Oracle JDBC Developer's Guide: Diagnosability in JDBC使用 ojdbc_g,Oracle JDBC Developer's Guide: Diagnosability in JDBC 中所述
Note, the 19.3 drivers are in Maven now, or just download manually.请注意,19.3 驱动程序现在在 Maven 中,或者只需手动下载。

        <dependency>
            <groupId>com.oracle.ojdbc</groupId>
            <artifactId>ojdbc8_g</artifactId>
            <version>19.3.0.0</version>
        </dependency>

You will also need Log4j JDK Logging Adapter您还需要Log4j JDK Logging Adapter

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jul</artifactId>
            <version>2.13.0</version>
        </dependency>

Set these System properties:设置这些系统属性:
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
-Doracle.jdbc.Trace=true

Configure your Loggers in log4j2.xmllog4j2.xml 中配置您的记录器

        <Logger name="oracle.jdbc" level="TRACE">
            <AppenderRef ref="Console"/>
        </Logger>
        <Logger name="oracle.sql" level="TRACE">
            <AppenderRef ref="Console"/>
        </Logger>

Note that level="ALL" will give the finest level of logging请注意, level="ALL"将提供最好的日志记录级别

Have you tried setting the corresponding system property?您是否尝试过设置相应的系统属性? eg.例如。 for TRACE:对于跟踪:

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

(from https://docs.oracle.com/cd/B28359_01/java.111/b31224/diagnose.htm ) (来自https://docs.oracle.com/cd/B28359_01/java.111/b31224/diagnose.htm

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Spring JDBC中启用SQL查询控制台日志记录 - How to enable sql queries console logging in spring JDBC 如何启用Oracle JDBC日志记录? - How to enable oracle jdbc logging? 在postgres jdbc驱动程序中记录准备好的sql语句 - Logging prepared sql statements in postgres jdbc driver 当将最新的jdbc驱动程序用于SQL Server 2005/2008时,准备好的语句,视图和存储过程如何比较性能? - When using the latest jdbc driver for SQL Server 2005/2008 how do prepared statements, views, and stored procedures compare regarding performance? 使用jdbc从Mule登录到SQL Server时无法打开数据库错误 - Cannot open database error when logging into SQL server from Mule using jdbc 如何使用JDBC获取正在运行的语句的列表 - How to get a list of running statements using JDBC 对于JDBC准备的语句,当在SQL语句中提供实际值时,如何确定变量的位置 - For JDBC prepared statements, how are the position of variables determined when an actual value is supplied in the SQL statement 在应用程序中记录SQL语句 - Logging SQL statements in application 如何使用pgAdmin配置插入语句的日志记录? - How to configure logging of insert statements using pgAdmin? 在不使用预准备语句的情况下防止JDBC中的SQL注入 - Preventing SQL Injection in JDBC without using Prepared Statements
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM