完整的 Spring Boot + Hibernate/JPA + P6Spy 配置指南

发布于:2025-08-03 ⋅ 阅读:(19) ⋅ 点赞:(0)

以下是完整的配置步骤,确保 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=?

常见问题解决方案

  1. 参数没有被替换

    • 确保 spy.properties 文件在 classpath 根目录

    • 检查 JDBC URL 是否正确添加了 jdbc:p6spy: 前缀

    • 确保没有其他日志框架覆盖了 P6Spy 的输出

  2. 与 HikariCP 的兼容性问题

    • 确保 HikariCP 的配置正确:

      yaml

      spring:
        datasource:
          hikari:
            driver-class-name: com.p6spy.engine.spy.P6SpyDriver
            jdbc-url: jdbc:p6spy:mysql://localhost:3306/your_database
  3. 性能问题

    • 生产环境中可以设置 filter=true 并排除不重要的表

    • 增加 executionThreshold 值只记录慢查询

  4. 多数据源配置

    • 每个数据源都需要单独配置 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 语句及其真实参数值,便于开发和调试。


网站公告

今日签到

点亮在社区的每一天
去签到