springboot集成log4jdbc -让SQL日志更加精彩

环境

框架: springboot 2.0

数据库: oracle mysql完全适用

日志: springboot使用默认的logback

log4jdbc介绍

使用java进行数据库操作时最痛苦的莫过于拼接SQL语句。在实际运行时往往需要查看实际生成的SQL语句和实际传入的参数,或许还会有查看SQL执行时间等的需求。
无论原生JDBC、dbutils、mybatis还是hibernate,使用log4j等日志框架可以看到生成的SQL,但是占位符和参数总是分开打印的。实在是不太友好。显示如下的效果:

select * from t_user where age>? and (sex=? or dept_id=?)

log4jdbc能很好的解决上述问题。使用log4jdbc之后的效果如下:

select * from t_user where age>1 and (sex=0 or dept_id='007')

集成log4jdbc

pom.xml中添加log4jdbc依赖

springboot默认使用logback,我们就使用logback作为我们的日志.这样我们在pom.xml中只需要引入log4jdbc依赖即可,不在需要其他日志框架的支持.

        
            com.googlecode.log4jdbc
            log4jdbc
            1.2
            runtime
        

application.xml中配置log4jdbc

spring.datasource.driver-class-name: net.sf.log4jdbc.DriverSpy
#使用log4jdbc后mysql的url
spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/xxxx?useUnicode=true&characterEncoding=UTF-8
#使用log4jdbc后oracle的url
#spring.datasource.url: jdbc:log4jdbc:oracle:thin:@127.0.0.1:1521:orcl
spring.datasource.driver-class-name: net.sf.log4jdbc.DriverSpy

在上面的配置中spring.datasource.driver-class-name使用net.sf.log4jdbc.DriverSpy.

使用net.sf.log4jdbc.DriverSpy.这个驱动后,不管我们使用的是mysql,oracle还是sql server,他都会帮我们尝试加载.

以下是它支持的可以自动尝试加载的驱动.

Driver Class Database Type
oracle.jdbc.driver.OracleDriver Older Oracle Driver
oracle.jdbc.OracleDriver Newer Oracle Driver
com.sybase.jdbc2.jdbc.SybDriver Sybase
net.sourceforge.jtds.jdbc.Driver jTDS SQL Server & Sybase driver
com.microsoft.jdbc.sqlserver.SQLServerDriver Microsoft SQL Server 2000 driver
com.microsoft.sqlserver.jdbc.SQLServerDriver Microsoft SQL Server 2005 driver
weblogic.jdbc.sqlserver.SQLServerDriver Weblogic SQL Server driver
com.informix.jdbc.IfxDriver Informix
org.apache.derby.jdbc.ClientDriver Apache Derby client/server driver, aka the Java DB
org.apache.derby.jdbc.EmbeddedDriver Apache Derby embedded driver, aka the Java DB
com.mysql.jdbc.Driver MySQL
org.postgresql.Driver PostgresSQL
org.hsqldb.jdbcDriver HSQLDB pure Java database
org.h2.Driver H2 pure Java database
spring.datasource.url: jdbc:log4jdbc:oracle:thin:@127.0.0.1:1521:orcl

使用了log4jdbc后,我们只需要在数据源url开头的jdbc后面添加**:log4jdbc**

修改前mysql和oracle的url
spring.datasource.url=jdbc:mysql://localhost:3306/xxxx?useUnicode=true&characterEncoding=UTF-8
spring.datasource.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl

修改后
spring.datasource.url=jdbc:log4jdbc:mysql://localhost:3306/xxxx?useUnicode=true&characterEncoding=UTF-8
spring.datasource.url=jdbc:log4jdbc:oracle:thin:@127.0.0.1:1521:orcl

到这里.我们就可以正常的使用log4jdbc了.

配置logback.xml(不必须)

我们使用了log4jdbc后,我们会明显看到我们日志量翻倍的增长. 这个数据量是非常巨大的. 我们需要设置logback配置文件,从而管理我们的日志.

我们的log4jdbc功能不光是将填充预编译语句的参数和执行时间,它还有其他的功能.

我们在项目src/main/resources下添加logback.xml文件. 文件内容如下:


<configuration debug="false">
    
    <property name="LOG_HOME" value="E://log/" />
    
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
        encoder>
    appender>
    
    <appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            
            <FileNamePattern>${LOG_HOME}/drp.log.%d{yyyy-MM-dd}.logFileNamePattern>
            
            <MaxHistory>30MaxHistory>
        rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
        encoder>
        
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MBMaxFileSize>
        triggeringPolicy>
    appender>
    
    <logger name="org.hibernate.type.descriptor.sql.BasicBinder"  level="OFF" />
    <logger name="org.hibernate.type.descriptor.sql.BasicExtractor"  level="OFF" />
    <logger name="org.hibernate.SQL" level="OFF" />
    <logger name="org.hibernate.engine.QueryParameters" level="OFF" />
    <logger name="org.hibernate.engine.query.HQLQueryPlan" level="OFF" />

 
    <root level="INFO">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    root>

    
    <include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
    
    <logger name="jdbc.sqlonly" level="OFF">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    logger>
    
    <logger name="jdbc.audit" level="OFF">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    logger>
    
    <logger name="jdbc.resultset" level="DEBUG">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    logger>

    
    <logger name="jdbc.connection" level="OFF">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    logger>
    
    <logger name="jdbc.sqltiming" level="DEBUG">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    logger>


configuration>

添加log4jdbc.properties文件(不必须)

如何只使用log4jdbc以上的预编译语句填充和执行时间显示,显得log4jdbc的功能有点太简单了. 其实log4jdbc功能还有很多. 如: 将慢的SQL记录为Error, 判断select,insert,update等语句那些输出到控制台.等等.都是非常好用实在的功能.

如果使用上面的功能,我们需要单独创建一个文件,来管理这些配置. 我们项目src/main/resources下创建log4jdbc.properties文件.并将下面内容添加到文件中.

#配置为需要记录的包或类匹配路径
#log4jdbc.debug.stack.prefix=com.drp
#log4jdbc加载的drivers (驱动名)
log4jdbc.drivers=oracle.jdbc.OracleDriver
log4jdbc.auto.load.popular.drivers=true
#在日志中显示warn警告
log4jdbc.statement.warn=true
#毫秒值.执行时间超过该值的SQL语句将被记录为warn级别.
log4jdbc.sqltiming.warn.threshold=2000
#毫秒值.执行时间超过该值的SQL语句将被记录为error级别.
log4jdbc.sqltiming.error.threshold=3000
#是把boolean记录为 'true'/'false' 还是 1/0. 默认设置为false,不启用,为了移植性.
#log4jdbc.dump.booleanastruefalse=true
#输出的sql,一行最大的字符数,默认90. 以后新版可能为0
#log4jdbc.dump.sql.maxlinelength=90
#如果在调试模式下转储,则转储整个堆栈跟踪  默认false
log4jdbc.dump.fulldebugstacktrace=false

#是否记录某些类型的语句,默认true
log4jdbc.dump.sql.select=true
log4jdbc.dump.sql.insert=true
log4jdbc.dump.sql.delete=true
log4jdbc.dump.sql.update=true
log4jdbc.dump.sql.create=true

#输出sql末尾处加入分号,默认false
#log4jdbc.dump.sql.addsemicolon=false

#将此设置为false以不修剪已记录的SQL
log4jdbc.trim.sql=true
#将此设置为false不删除额外的空行
log4jdbc.trim.sql.extrablanklines=true

#log4jdbc.suppress.generated.keys.exception=false

如下是log4jdbc能够配置的属性.

property default description since
log4jdbc.drivers

One or more fully qualified class names for JDBC drivers that log4jdbc should load and wrap. 
If more than one driver needs to be specified here, they should be comma separated with no spaces. 
This option is not normally needed because most popular JDBC drivers are already loaded by default-- 
this should be used if one or more additional JDBC drivers that (log4jdbc doesn't already wrap) 
needs to be included.
1.0
log4jdbc.auto.load.popular.drivers true Set this to false to disable the feature where popular drivers are automatically loaded. 
If this is false, you must set the log4jdbc.drivers property in order to load the driver(s) you want.
1.2beta2
log4jdbc.debug.stack.prefix

The partial (or full) package prefix for the package name of your application. 
The call stack will be searched down to the first occurrence of a class that has the matching prefix. 
If this is not set, the actual class that called into log4jdbc is used in the debug output 
(in many cases this will be a connection pool class.) For example, setting a system property 
such as this: -Dlog4jdbc.debug.stack.prefix=com.mycompany.myapp Would cause 
the call stack to be searched for the first call that came from code 
in the com.mycompany.myapp package or below, thus if all of your sql generating code 
was in code located in the com.mycompany.myapp package or any subpackages, 
this would be printed in the debug information, rather than the package name for a connection pool, 
object relational system, etc.
1.0
log4jdbc.sqltiming.warn.threshold

Millisecond time value. Causes SQL that takes the number of milliseconds specified or more time 
to execute to be logged at the warning level in the sqltiming log. 
Note that the sqltiming log must be enabled at the warn log level for this feature to work.
 Also the logged output for this setting will log with debug information that is normally only shown 
when the sqltiming log is enabled at the debug level. 
This can help you to more quickly find slower running SQL without adding overhead or logging 
for normal running SQL that executes below the threshold level (if the logging level is set appropriately.)
1.1beta1
log4jdbc.sqltiming.error.threshold

Millisecond time value. Causes SQL that takes the number of milliseconds specified or more time 
to execute to be logged at the error level in the sqltiming log. 
Note that the sqltiming log must be enabled at the error log level for this feature to work. 
Also the logged output for this setting will log with debug information that is normally only shown 
when the sqltiming log is enabled at the debug level. 
This can help you to more quickly find slower running SQL without adding overhead or logging 
for normal running SQL that executes below the threshold level (if the logging level is set appropriately.)
1.1beta1
log4jdbc.dump.booleanastruefalse false When dumping boolean values in SQL, dump them as 'true' or 'false'. 
If this option is not set, they will be dumped as 1 or 0 as many databases do not have a boolean type, 
and this allows for more portable sql dumping.
1.2alpha1
log4jdbc.dump.sql.maxlinelength 90 When dumping SQL, if this is greater than 0, than the dumped SQL will be broken up into lines 
that are no longer than this value. Set this value to 0 if you don't want log4jdbc to try 
and break the SQL into lines this way. In future versions of log4jdbc, this will probably default to 0.
1.2alpha1
log4jdbc.dump.fulldebugstacktrace false If dumping in debug mode, dump the full stack trace. 
This will result in EXTREMELY voluminous output, but can be very useful under some circumstances 
when trying to track down the call chain for generated SQL.
1.2alpha1
log4jdbc.dump.sql.select true Set this to false to suppress SQL select statements in the output. 1.2alpha1
log4jdbc.dump.sql.insert true Set this to false to suppress SQL insert statements in the output. 1.2alpha1
log4jdbc.dump.sql.update true Set this to false to suppress SQL update statements in the output. 1.2alpha1
log4jdbc.dump.sql.delete true Set this to false to suppress SQL delete statements in the output. 1.2alpha1
log4jdbc.dump.sql.create true Set this to false to suppress SQL create statements in the output. 1.2alpha1
log4jdbc.dump.sql.addsemicolon false Set this to true to add an extra semicolon to the end of SQL in the output. 
This can be useful when you want to generate SQL from a program with log4jdbc in order to 
create a script to feed back into a database to run at a later time.
1.2alpha1
log4jdbc.statement.warn false Set this to true to display warnings (Why would you care?) in the log when Statements are used 
in the log. NOTE, this was always true in releases previous to 1.2alpha2. It is false by default 
starting with release 1.2 alpha 2.
1.2alpha2
log4jdbc.trim.sql true Set this to false to not trim the logged SQL. (Previous versions always trimmed the SQL.) 1.2beta2
log4jdbc.trim.sql.extrablanklines true Set this to false to not trim extra blank lines in the logged SQL 
(by default, when more than one blank line in a row occurs, the contiguous lines are collapsed to 
just one blank line.) (Previous versions didn't trim extra blank lines at all.)
1.2
log4jdbc.suppress.generated.keys.exception false Set to true to ignore any exception produced by the method, Statement.getGeneratedKeys() 
(Useful for using log4jdbc with Coldfusion.)
1.2beta2

到这里. 打印到控制台上的效果如下.(控制台式没有彩色的,我这里使用了idea的Grep console插件将日志按等级变成不同颜色) 我们可以看到jdbc.sqltiming 显示了sql并显示了执行时间1毫秒

jdbc.resultset 显示结果集. 我这里是查询一条数据. 它将每一个字段的值都输出为一行日志.

springboot集成log4jdbc -让SQL日志更加精彩_第1张图片

下图中,我把sql执行超过3毫秒的sql设置为error,我们可以看到显示了ERROR.

springboot集成log4jdbc -让SQL日志更加精彩_第2张图片

问题: 使用log4jdbc, 我们改写了application.properties中的驱动和url. 这使得的如果我们想使用阿里druid这样的数据库连接池时,应为无法识别驱动造成的无法使用.

所以log4jdbc还是更更适用与开发环境中.

参考:

https://www.cnblogs.com/cnjavahome/p/8421846.html

https://blog.csdn.net/hylexus/article/details/52552140

https://blog.csdn.net/u011686226/article/details/68926954

你可能感兴趣的:(springboot)