Hibernate日志打印sql参数

本文将从多个方面介绍如何在Hibernate中打印SQL参数。Hibernate作为一种ORM框架,可以通过打印SQL参数方便开发者调试和优化Hibernate应用。

一、通过配置开启SQL参数日志打印

在Hibernate的配置文件中,可以通过设置show_sqlformat_sql选项来开启打印SQL语句和格式化打印。

<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>

如果在Hibernate应用中开启了这两个选项,Hibernate会在控制台输出每个执行的SQL语句以及其参数。但是这种方式无法输出参数的值。

二、通过自定义日志打印器实现SQL参数日志打印

在Hibernate中,可以通过实现org.hibernate.resource.jdbc.spi.StatementInspector接口来自定义SQL语句的日志打印行为。


public class MyStatementInspector implements StatementInspector {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyStatementInspector.class);

    @Override
    public String inspect(String sql) {
        LOGGER.info("SQL执行语句: {}", sql);
        return sql;
    }

    @Override
    public  T inspect(T entity) {
        return entity;
    }
}

通过实现StatementInspector接口并重写inspect()方法,可以在每次SQL执行语句时记录SQL语句并输出到日志中。如果想要输出SQL语句中的参数,可以将sql字符串转换为PreparedStatement对象,并调用getParameter()方法获取参数的实际值。


public class MyStatementInspector implements StatementInspector {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyStatementInspector.class);

    @Override
    public String inspect(String sql) {
        LOGGER.info("SQL执行语句: {}", sql);
        try {
            PreparedStatement preparedStatement = JdbcServicesImpl.GROUP_JDBC_SERVICES.prepare(sql, false);
            ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();
            for (int i = 1; i <= parameterMetaData.getParameterCount(); i++) {
                Object paramValue = preparedStatement.getParameter(i);
                LOGGER.info("参数{}: {}", i, paramValue);
            }
        } catch (Exception e) {
            LOGGER.error("获取参数出错", e);
        }
        return sql;
    }

    @Override
    public  T inspect(T entity) {
        return entity;
    }
}

可以通过将自定义的StatementInspector实例设置到Hibernate的physical-sql-inspector属性中来启用该功能:

<session-factory>
  <property name="hibernate.physical-sql-inspector">mypackage.MyStatementInspector</property>
</session-factory>

三、通过AOP拦截器实现SQL参数日志打印

除了自定义StatementInspector外,还可以利用AOP拦截器的方式来实现SQL参数的日志打印。


@Aspect
@Component
public class SqlParamLogAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(SqlParamLogAspect .class);

    @Around("execution(* org.hibernate.SQLQuery.uniqueResult(..)) " +
            "|| execution(* org.hibernate.SQLQuery.list(..)) " +
            "|| execution(* org.hibernate.internal.AbstractQueryImpl.uniqueResult(..)) " +
            "|| execution(* org.hibernate.internal.AbstractQueryImpl.list(..)) " +
            "|| execution(* org.hibernate.loader.Loader.executeQueryStatement(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        String sql = null;
        Object[] args = pjp.getArgs();
        if (args.length > 0) {
            sql = (String) args[0];
        }
        try {
            Object result = pjp.proceed();
            LOGGER.info("SQL执行语句: {}", sql);
            if (args.length > 1 && args[1] instanceof QueryParameters) {
                QueryParameters queryParams = (QueryParameters) args[1];
                TreeMap map = new TreeMap<>();
                int i = -1;
                for (TypedValue tv : queryParams.getPositionalParameterValues()) {
                    i++;
                    LOGGER.info("参数{}: {}", i, tv.getValue());
                }
                LOGGER.info("");
            }
            return result;
        } catch (Throwable throwable) {
            LOGGER.error("SQL执行出错: {}", sql, throwable);
            throw throwable;
        }
    }
}

通过在Hibernate执行SQL语句的关键方法上添加AOP切面,可以截获执行的SQL语句以及参数,将SQL语句和参数同时输出到日志中。

四、通过ORM框架实现SQL参数日志打印

除了上述方法以外,我们还可以使用第三方ORM框架来实现SQL参数的日志打印。如:P6Spy

P6Spy是一个Java开发的ORM框架,可以截获Java应用程序发往数据库的SQL语句并将其输出到日志中。可以通过添加P6Spy的JDBC Driver来替换Hibernate默认的JDBC Driver,以截获Hibernate执行的SQL语句,并在日志中输出SQL参数。

<!-- 引入P6Spy JDBC Driver -->
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.6.0</version>
</dependency>

接下来,在hibernate.cfg.xml文件中将hibernate.connection.driver_class属性设置为P6Spy的JDBC Driver:

<property name="hibernate.connection.driver_class">com.p6spy.engine.spy.P6SpyDriver</property>

最后,在p6spy.properties文件中配置日志输出:

module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.logging.appender.StdoutLogger
realdriver=org.sqlite.SQLiteDriver
driverlist=org.sqlite.JDBC

配置完成后,P6Spy会拦截Hibernate执行的每个SQL语句,并将其输出到控制台或文件中,同时也会输出SQL语句的参数。

原创文章,作者:ZPNAH,如若转载,请注明出处:https://www.506064.com/n/375368.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
ZPNAH的头像ZPNAH
上一篇 2025-04-29 12:49
下一篇 2025-04-29 12:49

相关推荐

  • 三星内存条参数用法介绍

    本文将详细解释三星内存条上面的各种参数,让你更好地了解内存条并选择适合自己的一款。 一、容量大小 容量大小是内存条最基本的参数,一般以GB为单位表示,常见的有2GB、4GB、8GB…

    编程 2025-04-29
  • Python3定义函数参数类型

    Python是一门动态类型语言,不需要在定义变量时显示的指定变量类型,但是Python3中提供了函数参数类型的声明功能,在函数定义时明确定义参数类型。在函数的形参后面加上冒号(:)…

    编程 2025-04-29
  • Spring Boot中发GET请求参数的处理

    本文将详细介绍如何在Spring Boot中处理GET请求参数,并给出完整的代码示例。 一、Spring Boot的GET请求参数基础 在Spring Boot中,处理GET请求参…

    编程 2025-04-29
  • Python input参数变量用法介绍

    本文将从多个方面对Python input括号里参数变量进行阐述与详解,并提供相应的代码示例。 一、基本介绍 Python input()函数用于获取用户输入。当程序运行到inpu…

    编程 2025-04-29
  • Cron执行日志用法介绍

    本文将从多个方面对cron执行日志进行详细阐述,包括cron执行日志的定义、cron执行日志的产生原因、cron执行日志的格式以及如何解读cron执行日志。 一、定义 Cron是一…

    编程 2025-04-29
  • Python函数名称相同参数不同:多态

    Python是一门面向对象的编程语言,它强烈支持多态性 一、什么是多态多态是面向对象三大特性中的一种,它指的是:相同的函数名称可以有不同的实现方式。也就是说,不同的对象调用同名方法…

    编程 2025-04-29
  • Python Class括号中的参数用法介绍

    本文将对Python中类的括号中的参数进行详细解析,以帮助初学者熟悉和掌握类的创建以及参数设置。 一、Class的基本定义 在Python中,通过使用关键字class来定义类。类包…

    编程 2025-04-29
  • Hibernate注解联合主键 如何使用

    解答:Hibernate的注解方式可以用来定义联合主键,使用@Embeddable和@EmbeddedId注解。 一、@Embeddable和@EmbeddedId注解 在Hibe…

    编程 2025-04-29
  • 使用SQL实现select 聚合查询结果前加序号

    select语句是数据库中最基础的命令之一,用于从一个或多个表中检索数据。常见的聚合函数有:count、sum、avg等。有时候我们需要在查询结果的前面加上序号,可以使用以下两种方…

    编程 2025-04-29
  • 理解Mybatis中的SQL Limit用法

    Mybatis是一种非常流行的ORM框架,提供了SQL映射配置文件,可以使用类似于传统SQL语言的方式编写SQL语句。其中,SQL的Limit语法是一个非常重要的知识点,能够实现分…

    编程 2025-04-29

发表回复

登录后才能评论