以下是完整的配置步骤,确保 P6Spy 能正确显示带有真实参数的 SQL 语句。
1. 完整依赖配置
Maven (pom.xml
)
xml
<dependencies> <!-- Spring Boot Starter Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 数据库驱动 (以MySQL为例) --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- P6Spy 核心依赖 --> <dependency> <groupId>p6spy</groupId> <artifactId>p6spy</artifactId> <version>3.9.1</version> </dependency> <!-- 可选:如果你使用HikariCP连接池 --> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> </dependency> </dependencies>
2. 完整的 application.yml
配置
yaml
spring: datasource: url: jdbc:p6spy:mysql://localhost:3306/your_database?useSSL=false&serverTimezone=UTC username: your_username password: your_password driver-class-name: com.p6spy.engine.spy.P6SpyDriver hikari: # HikariCP 配置 pool-name: SpringBootHikariCP auto-commit: false connection-timeout: 30000 maximum-pool-size: 20 minimum-idle: 5 max-lifetime: 1800000 jpa: show-sql: false # 禁用原生Hibernate的SQL日志 properties: hibernate: format_sql: true use_sql_comments: true # 禁用Hibernate的统计信息(避免与P6Spy冲突) generate_statistics: false # 使用P6Spy作为SQL日志记录器 session_factory.statement_inspector: com.p6spy.engine.spy.P6SpyLogger logging: level: com.p6spy: DEBUG # 设置P6Spy日志级别
3. spy.properties
完整配置
在 src/main/resources
下创建:
properties
# 基本模块配置 module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory # 日志输出方式(使用SLF4J) appender=com.p6spy.engine.spy.appender.Slf4JLogger # 自定义日志格式(显示时间、执行时间、SQL) logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat customLogMessageFormat=%(executionTime) ms | SQL: %(sqlSingleLine) # 是否显示二进制字段 excludebinary=true # 过滤配置 #filter=false #exclude=QRTZ_* # 排除特定表 # 批处理配置 executionThreshold=100 # 只记录执行超过100ms的SQL # 日期格式 dateformat=yyyy-MM-dd HH:mm:ss # 是否记录JDBC连接事件 logConnect=false # 是否记录提交事件 logCommit=false # 是否记录回滚事件 logRollback=false
4. 高级自定义配置(可选)
自定义日志格式类
java
package com.yourpackage.config; import com.p6spy.engine.spy.appender.MessageFormattingStrategy; import org.hibernate.engine.jdbc.internal.BasicFormatterImpl; import org.hibernate.engine.jdbc.internal.Formatter; public class PrettySqlFormat implements MessageFormattingStrategy { private static final Formatter SQL_FORMATTER = new BasicFormatterImpl(); @Override public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql, String url) { if (sql.isEmpty()) { return ""; } String formattedSql = SQL_FORMATTER.format(sql) .replace("\n", "\n\t"); return String.format( "Hibernate: %s %s {elapsed: %dms}", category, formattedSql, elapsed); } }
然后在 spy.properties
中引用:
properties
logMessageFormat=com.yourpackage.config.PrettySqlFormat
5. 验证配置是否生效
启动应用后,你应该能在日志中看到类似这样的输出:
text
15 ms | SQL: select * from user where id=1 and name='John'
而不是预处理语句:
text
select * from user where id=? and name=?
常见问题解决方案
参数没有被替换:
确保
spy.properties
文件在 classpath 根目录检查 JDBC URL 是否正确添加了
jdbc:p6spy:
前缀确保没有其他日志框架覆盖了 P6Spy 的输出
与 HikariCP 的兼容性问题:
确保 HikariCP 的配置正确:
yaml
spring: datasource: hikari: driver-class-name: com.p6spy.engine.spy.P6SpyDriver jdbc-url: jdbc:p6spy:mysql://localhost:3306/your_database
性能问题:
生产环境中可以设置
filter=true
并排除不重要的表增加
executionThreshold
值只记录慢查询
多数据源配置:
每个数据源都需要单独配置 P6Spy:
java
@Bean @Primary public DataSource primaryDataSource() { return DataSourceBuilder.create() .url("jdbc:p6spy:mysql://host1/db") .driverClassName("com.p6spy.engine.spy.P6SpyDriver") .build(); } @Bean public DataSource secondaryDataSource() { return DataSourceBuilder.create() .url("jdbc:p6spy:mysql://host2/db") .driverClassName("com.p6spy.engine.spy.P6SpyDriver") .build(); }
这样配置后,P6Spy 将能完整记录所有 SQL 语句及其真实参数值,便于开发和调试。