本文将从多个方面介绍如何在Hibernate中打印SQL参数。Hibernate作为一种ORM框架,可以通过打印SQL参数方便开发者调试和优化Hibernate应用。
一、通过配置开启SQL参数日志打印
在Hibernate的配置文件中,可以通过设置show_sql
和format_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