commons-dbutils logback 如何打印sql
时间: 2025-08-05 11:02:47 浏览: 7
<think>我们有一个使用commons-dbutils和logback的项目,需要配置日志输出执行的SQL语句。commons-dbutils本身不提供直接的SQL日志记录,但我们可以通过配置logback来记录SQL语句。通常,这需要数据库驱动或连接层支持日志记录,或者使用像p6spy这样的第三方工具来拦截和记录SQL。
然而,根据用户提供的引用,特别是引用[2]中提到了p6spy的配置,我们可以考虑使用p6spy来拦截SQL并输出日志。同时,用户项目已经使用了logback,所以我们可以将p6spy的日志输出到logback。
步骤:
1. 添加p6spy依赖
2. 配置p6spy(spy.properties)
3. 修改数据库连接配置,使用p6spy驱动
4. 配置logback来输出p6spy的日志
但是,用户特别提到了commons-dbutils,这是一个JDBC的轻量级封装工具。我们不需要修改commons-dbutils的代码,只需要修改数据源配置,将原来的数据库驱动替换为p6spy的驱动,然后p6spy会代理真实的数据库驱动,并拦截SQL语句进行日志输出。
具体步骤:
1. 添加p6spy依赖:
在Maven项目中,添加以下依赖(注意版本,这里使用较新的版本):
```xml
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version> <!-- 请检查最新版本 -->
</dependency>
```
2. 创建spy.properties配置文件(放在资源目录下,如src/main/resources/spy.properties):
内容参考用户引用[2]中的配置,但需要根据实际情况调整。例如:
```properties
# 3.2.1以上使用
modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印,这里使用用户引用[2]中提到的格式,但注意用户引用[2]中提到了MybatisPlusLogFactory,但我们不是MybatisPlus项目,所以使用默认的或者自定义的格式
# 使用logback,我们可以将appender设置为Slf4JLogger,这样日志会通过slf4j输出,然后由logback配置控制
appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置日志格式,可以使用自定义格式,但这里我们使用用户引用[2]中的格式,但注意那个格式是MybatisPlus的,我们可以使用默认的或者简单的
# 如果不想使用MybatisPlus的格式,可以去掉logMessageFormat配置,或者使用默认的
# logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat
# 或者使用自定义格式类(如果需要的话)
# 但通常我们可以使用内置的格式,比如:com.p6spy.engine.spy.appender.SingleLineFormat
# 使用以下配置来输出单行日志(可选)
logMessageFormat=com.p6spy.engine.spy.appender.SingleLineFormat
# 使用日志系统记录sql,上面已经配置了Slf4JLogger
# 配置记录Log例外(排除一些类别,减少日志量)
excludecategories=info,debug,result,commit,resultset,batch
# 实际数据库驱动(根据你的数据库配置)
driverlist=com.mysql.cj.jdbc.Driver # 这里以MySQL为例,请替换为你的数据库驱动
# 是否开启慢SQL记录
outagedetection=true
outagedetectioninterval=2 # 慢SQL阈值(秒)
```
3. 修改数据源配置:将原来的数据库驱动替换为`com.p6spy.engine.spy.P6SpyDriver`,并将原来的URL加上`jdbc:p6spy:`前缀。
例如,原来的URL可能是:`jdbc:mysql://localhost:3306/mydb`
修改后:`jdbc:p6spy:mysql://localhost:3306/mydb`
4. 配置logback.xml(或logback-spring.xml)来输出p6spy的日志:
在logback配置文件中,为p6spy设置一个logger,指定日志级别为DEBUG或INFO(根据需求)。
例如:
```xml
<configuration>
<!-- 其他配置 -->
<logger name="com.p6spy" level="DEBUG" additivity="false">
<appender-ref ref="CONSOLE" /> <!-- 假设你有一个名为CONSOLE的控制台appender -->
<!-- 如果需要同时输出到文件,可以添加文件appender -->
</logger>
<!-- 其他配置 -->
</configuration>
```
这样配置后,当commons-dbutils执行SQL时,p6spy会拦截SQL语句并通过slf4j记录日志,然后由logback输出。
注意:使用p6spy可能会对性能有一定影响,因为它会拦截并处理所有的数据库操作。在生产环境中,如果日志量很大,请谨慎开启。
另外,如果不想使用p6spy,也可以考虑使用数据库驱动自带的日志功能(如MySQL驱动有logger配置),但配置方式可能因驱动而异,且通常不如p6spy统一和灵活。
根据用户引用[3]中提到了使用Druid连接池,如果用户使用的是Druid连接池,那么Druid本身也提供了SQL日志记录功能(通过Filter)。但是用户问题中指定了commons-dbutils和logback,并且没有明确说使用Druid,所以这里我们采用通用的p6spy方案。
如果用户使用的是Druid,那么可以配置Druid的StatFilter并启用SQL日志记录,然后通过logback输出Druid的日志。但注意,Druid的日志记录的是执行统计信息,而不是每条SQL的完整语句(除非配置了logFilter)。不过,用户引用[3]中并没有详细说明如何配置Druid来记录SQL语句,所以我们不展开。
综上所述,使用p6spy是相对通用的方法。
相关问题:
1. 在使用p6spy时,如何排除某些特定的SQL语句不被记录?
2. p6spy对性能的影响有多大?如何优化?
3. 除了p6spy,还有哪些方法可以记录SQL日志?
4. 如何配置logback只输出SQL日志到单独的文件?
5. 在Spring项目中如何集成p6spy?</think>要配置commons-dbutils和logback输出执行的SQL语句,可通过以下步骤实现:
### 解决方案
#### 1. **添加P6Spy依赖(SQL拦截工具)**
在`pom.xml`中添加依赖(替代原生JDBC驱动):
```xml
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>3.9.1</version> <!-- 使用最新版本 -->
</dependency>
```
P6Spy会拦截真实数据库驱动,记录SQL并输出日志[^2]。
#### 2. **配置P6Spy代理**
创建`src/main/resources/spy.properties`:
```properties
# 指定真实数据库驱动(如MySQL)
driverlist=com.mysql.cj.jdbc.Driver
# 使用SLF4J输出日志(与logback集成)
appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 自定义日志格式(显示SQL和执行时间)
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
customLogMessageFormat=%(executionTime)ms | %(category) | SQL: %(sqlSingleLine)
# 启用慢查询检测(超过2秒报警)
outagedetection=true
outagedetectioninterval=2
```
此配置将SQL日志重定向到SLF4J,由logback处理[^2]。
#### 3. **修改数据库连接配置**
将原JDBC连接替换为P6Spy代理:
```diff
- url: jdbc:mysql://localhost:3306/db
+ url: jdbc:p6spy:mysql://localhost:3306/db
- driver: com.mysql.cj.jdbc.Driver
+ driver: com.p6spy.engine.spy.P6SpyDriver
```
P6Spy会拦截所有SQL操作并记录[^2][^3]。
#### 4. **配置logback输出SQL日志**
在`logback.xml`中增加:
```xml
<!-- 单独记录SQL日志到文件 -->
<appender name="SQL_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/sql.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %msg%n</pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/sql.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
</rollingPolicy>
</appender>
<!-- 设置P6Spy日志级别 -->
<logger name="com.p6spy" level="DEBUG" additivity="false">
<appender-ref ref="SQL_FILE"/> <!-- 输出到文件 -->
<appender-ref ref="CONSOLE"/> <!-- 可选:同时输出到控制台 -->
</logger>
```
此时执行的SQL会以如下格式记录:
```
2023-05-01 12:30:45 5ms | statement | SQL: SELECT * FROM users WHERE id=?
```
### 关键点说明
1. **原理**
P6Spy作为代理驱动,拦截所有JDBC操作,将SQL通过SLF4J传递给logback[^2]。
2. **事务安全**
日志记录不影响实际事务提交/回滚机制[^3][^4]。
3. **性能影响**
生产环境建议:
- 关闭结果集日志:`excludecategories=resultset`
- 仅记录慢查询:设置`outagedetectioninterval=500`(500ms)
### 相关问题
1. **如何排除特定SQL不记录?**
在`spy.properties`中使用`excludecategories`过滤`batch,info`等操作[^2]。
2. **P6Spy与Druid连接池如何共存?**
需将Druid的驱动改为P6Spy驱动,保持连接池配置不变[^3]。
3. **如何格式化输出的SQL语句?**
自定义`logMessageFormat`实现类,或使用内置的`MultiLineFormat`(需添加`%b`换行符)。
4. **日志中出现乱码如何解决?**
在logback的`<encoder>`中增加`<charset>UTF-8</charset>`声明编码。
5. **能否不引入P6Spy直接记录SQL?**
Commons-DButils无内置日志能力,需依赖第三方工具(如P6Spy)或扩展`QueryRunner`类重写方法。
[^1]: 日志整合是开发和运维的关键环节。
[^2]: P6Spy通过代理驱动实现SQL拦截和日志输出。
[^3]: JDBC连接配置的变更是实现代理的核心步骤。
[^4]: 日志工具不应影响实际事务执行逻辑。
阅读全文
相关推荐












