ITPub博客

首页 > 数据库 > 数据库开发技术 > 关于PostgreSQL JDBC中的log输出是怎么回事?

关于PostgreSQL JDBC中的log输出是怎么回事?

原创 数据库开发技术 作者:数据库杂记 时间:2024-04-04 10:23:40 0 删除 编辑

前言

自上一篇:挖一挖:PostgreSQL Java里的double类型存储到varchar精度丢失问题写完之后,有热心的朋友, 就发留言问,那个log配置了半天,好像不太管用。就是说,用了自定义的配置文件,最后都不起作用,看不到有效的输出。

首先强调一下,PG数据库的外围生态是非常完善的,就是说,它几乎支持各种主流的访问接口,这个完全为亚于当规模最大使用范围最广的一些大型商用数据库。从这个角度来看,它的发展前景不可限量 ,最贴近它自身的外围用户不就是使用这些访问接口的广大开发人员吗?

分析与实作

上一篇文章提到:这个需要设置logging.properties. 详情可以参考文档:https://jdbc.postgresql.org/documentation/logging/。当时限于篇幅和侧重于问题本身,就没有展开说明。

这个文档说的太简单了,如果按照它上边说的,可能真的看不到日志输出 。它上边是这么说的:

先自定义一个logging.properties,  大致内容如下:

# Specify the handler, the handlers will be installed during VM startup.
handlers = java.util.logging.FileHandler

# Default global logging level.
.level = OFF

# Default file output is in user's home directory.
java.util.logging.FileHandler.pattern = %h/pgjdbc%u.log
java.util.logging.FileHandler.limit = 5000000
java.util.logging.FileHandler.count = 20
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level = FINEST

java.util.logging.SimpleFormatter.format = %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n

# Facility specific properties.
org.postgresql.level = FINEST

上边最后一行是关键。

然后你在你的JDBC访问PG的程序里,使用下边的命令行启动,即可以看到对应的LOG输出 。

java -jar -Djava.util.logging.config.file=logging.properties run.jar

事实上,看不到。

我们继续搬出前篇文章中的代码:

package org.example;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.logging.LogManager;

public class Main {
    public static void main(String[] args) throws IOException {

        String sql="insert into t1 values(?)";
        try ( Connection connection =
                      DriverManager.getConnection("jdbc:postgresql://192.168.0.6:5432/mydb",
                              "mydb", "test123");
              PreparedStatement ps=  connection.prepareStatement(sql);
        ) {
            ps.setObject(1,new Double(48));ps.execute();
            ps.setObject(1,new Double(48.1));ps.execute();
            ps.setObject(1,new Double(48.9));ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

这样编译后,执行上边的命令行是看不到LOG的。或者官方文档有时候也是有些偷懒。系统属性:java.util.logging.config.file可能在这里头并没有起到作用。解决的办法有下边两种:

1、直接使用默认的logging.properties

找到你的%JAVA_HOME%\jre\lib\logging.properties,  然后修改它,在末尾加上那一行:

java.util.logging.ConsoleHandler.level = FINEST
org.postgresql.level = FINEST

这样做,就可以在控制台上看到详细的日志输出。

或者:

handlers= java.util.logging.FileHandler

java.util.logging.FileHandler.pattern = d:/pgjdbc.log
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level = FINEST
org.postgresql.level = FINEST

这样你仍然能在你的d:\pgjdbc.log里头看到完整的日志。

四月 04, 2024 9:50:25 上午 org.postgresql.Driver loadDefaultProperties
详细: Loading driver configuration via classloader sun.misc.Launcher$AppClassLoader@18b4aac2
四月 04, 2024 9:50:25 上午 org.postgresql.Driver connect
详细: Connecting with URL: jdbc:postgresql://192.168.0.6:5432/mydb
四月 04, 2024 9:50:25 上午 org.postgresql.jdbc.PgConnection <init>
详细: PostgreSQL JDBC Driver 42.7.3
四月 04, 2024 9:50:25 上午 org.postgresql.jdbc.PgConnection setDefaultFetchSize
详细:   setDefaultFetchSize = 0
四月 04, 2024 9:50:25 上午 org.postgresql.jdbc.PgConnection setPrepareThreshold
详细:   setPrepareThreshold = 5
....................

2、使用代码加载自定义的logging.properties

内容与上边定义的相同。只是在代码里头要进行一定程度的处理。

完整的代码是:

public class Main {
    public static void main(String[] args) throws IOException {
        //1.通过类加载器 读取配置文件
        InputStream inputStream = Main.class.getClassLoader().getResourceAsStream("logging.properties");
        //2.创建LogManager
        LogManager logManager = LogManager.getLogManager();
        //3.通过LogManger加载配置文件
        logManager.readConfiguration(inputStream);


        String sql="insert into t1 values(?)";
        try ( Connection connection =
                      DriverManager.getConnection("jdbc:postgresql://192.168.0.6:5432/mydb",
                              "mydb", "test123");
              PreparedStatement ps=  connection.prepareStatement(sql);
        ) {
            ps.setObject(1,new Double(48));ps.execute();
            ps.setObject(1,new Double(48.1));ps.execute();
            ps.setObject(1,new Double(48.9));ps.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

上边的第4行至第9行那里头的3行代码,就是强制性的加载自定义的配置文件,让其生效。这样设置完以后,执行出来的结果 ,是可以看到日志文件:%h/pgjdbc%u.log,通常就是pgjdbc.log.0, pgjdbc.log.1之类的文件。

总结 :

pg-jdbc使用的是JDK自带的JUL日志框架来输出 日志,这是可以理解的,它想尽量减少对外围第三方库的依赖。但是在生产环境当中使用大量第三方库的时候,可能就要注意了,往往是混合着多种日志框架,比如log4j2,  logback等。这就需要通过Slf4j等进行集成,让所有的logger都能正常工作。

有效的日志输出能帮我们判断并解决大量的问题,也有助于了解PG更底层的运行细节。这与代码的简单DEBUG,效果完全不一样。





原文作者:数据库杂记;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-04-22

  • 博文量
    276
  • 访问量
    160332