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

Posted

技术标签:

【中文标题】如何在休眠中记录失败的sql?【英文标题】:How to log failed sql in hibernate? 【发布时间】:2019-07-08 04:07:47 【问题描述】:

我正在使用 spring-data-jpa 构建一个 SpringBoot 应用程序。我知道如何从这个问题记录所有 sql。 How to print a query string with parameter values when using Hibernate

但如果我只想记录失败的 sql 怎么办?

【问题讨论】:

你没有在相应的 SQLException 中得到那些吗? 我得到了异常,它只是告诉我xx 在插入大量记录时不能为空,我需要调试哪个抛出了这个异常。 【参考方案1】:

有两种选择:

    使用参数值配置 sql 日志记录。禁用 jdbc 批处理并通过休眠方式启用刷新。 添加调试 JDBC 驱动程序,例如 p6spy,其功能或多或少与上述完全一致。

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

    SELECT 查询,默认情况下您已开启刷新。因此,当发生错误时,您可以确切地知道哪个查询失败了。 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语句都立即刷新到数据库中。 https://p6spy.readthedocs.io/en/latest/configandusage.html

【讨论】:

【参考方案2】:

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

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

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

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

    
    配置 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>

【讨论】:

以上是关于如何在休眠中记录失败的sql?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用休眠本机查询获取单个记录字符串值?

如何使用休眠插入加密数据

如何在休眠本机 SQL 中处理模式

如何使用休眠执行 sql-script 文件?

如何使用 JPA 和休眠映射 Java/Kotlin 字符串数组和 Postgres SQL 数组

如何在休眠中使用 UNION 执行查询