当前位置: 代码迷 >> java >> 如何在休眠中记录失败的 sql?
  详细解决方案

如何在休眠中记录失败的 sql?

热度:31   发布时间:2023-07-31 13:45:12.0

我正在使用 spring-data-jpa 构建一个 SpringBoot 应用程序。 我知道如何从这个问题记录所有 sql。

但是如果我只想记录失败的 sql 呢?

有两种选择:

  1. 使用参数值配置 sql 日志记录。 禁用 jdbc 批处理并通过休眠方式启用刷新。
  2. 添加调试 JDBC 驱动程序,例如 p6spy,它们或多或少会完全按照上述说明进行操作。

首先,我们来分析问题,将查询类型拆分为SELECT 和INSERT/UPDATE 查询。

  1. 默认情况下,您对它们进行SELECT 查询 因此,当发生错误时,您可以确切地知道哪个查询失败了。
  2. INSERT/UPDATE 查询,这里事情变得棘手,因为您的刷新将关闭并且您有查询批处理,这意味着首先当您运行查询时它会被延迟。 其次,它与其他不相关的查询打包在一起,第三,Hibernate 可能会对它们重新排序。 所以简短的回答是,如果您单独使用休眠,这对于 INSERT/UPDATE 是不可行的。

您的问题的解决方案基本上需要做两件事: 1. 它应该记录查询及其参数值。 这可以通过以下方式完成:

# logs the SQL statements
log4j.logger.org.hibernate.SQL=debug 

# Logs the JDBC parameters passed to a query
log4j.logger.org.hibernate.type=trace 

2. 解决方案需要关闭批处理查询,否则,你会得到一堆SQL,但你不知道究竟哪个SQL是有问题的。

hibernate.jdbc.batch_size=1

不确定这是否足以完全禁用批处理,但您需要找出答案。

或者,您可以使用专为 DEBUG 设计的 jdbc 驱动程序。 这将是 p6spy 驱动程序,它可以选择刷新每个 SQL 语句,这正是您想要的。

这里需要设置autoflush=true配置参数,以确保每条 sql 语句都立即刷新到数据库中。

这为您提供了多个日志条目。 就我而言,这是不受欢迎的。
这是我的解决方案:

  1. 依赖 net.ttddyy:datasource-proxy:1.6
  2. 在 Spring 配置中包装数据源

    @Bean
    public DataSource dataSource() {
      return ProxyDataSourceBuilder.create(originalDatasource())
             .logQueryBySlf4j(FLF4JLogLevel.DEBUG).build();
    }
  1. 编写您自己的 LogAppender - 在这里您可以过滤日志事件,因此您可以过滤 ie 仅插入或执行失败

public class SQLAppender extends AppenderBase
[...]
    @Override
    protected void append(ILoggingEvent eventObject) {
    [...]

    }
  1. 配置 logback.xml

 <appender name="mySQLAppender" class="com.my.SQLAppender" > </appender> <logger name="net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener" level="DEBUG"\\> <appender-ref ref="mySQLAppender"/> </logger>

  相关解决方案