首页 > 编程知识 正文

Hibernate日志打印sql参数

时间:2023-11-21 04:31:23 阅读:292439 作者:NIZC

本文将从多个方面介绍如何在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语句的参数。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。