在Java开发中打印原生SQL语句主要有以下几种实现方式:
1.JDBC原生方式
- 通过PreparedStatement的toString()方法可直接打印带参数的完整SQL
- 需注意不同数据库驱动实现差异(如MySQL需强制转换为ClientPreparedStatement)
示例代码:
PreparedStatement ptmt = conn.prepareStatement("SELECT * FROM users WHERE id=?");
ptmt.setInt(1, 100);
System.out.println(((ClientPreparedStatement)ptmt).asSql()); // MySQL特有方式
System.out.println(ptmt.toString()); // 通用方式
2.日志框架配置
- 配置log4j/logback等日志框架的SQL日志级别为DEBUG
- 针对不同框架设置特定logger(如Hibernate需配置
org.hibernate.SQL
)
log4j2.xml示例配置:
<Logger name="org.hibernate.SQL" level="DEBUG"/> <Logger name="org.hibernate.type.descriptor.sql" level="TRACE"/>
3.MyBatis专用方案
- 使用
mybatis-log-ultra
插件可直接转换预编译SQL为可执行语句 - 配置mybatis-config.xml启用STDOUT_LOGGING
<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
4.Spring生态工具
- 使用P6Spy代理JDBC驱动实现SQL拦截
- 配置log4jdbc替换原生驱动(需修改jdbc连接前缀)
spring.datasource.url=jdbc:log4jdbc:mysql://localhost/db
5.AOP拦截方案
- 通过MyBatis拦截器获取BoundSql对象
- 自定义StatementHandler拦截SQL执行过程
关键代码片段:
@Intercepts(@Signature(type=StatementHandler.class, method="query"))
public class SqlInterceptor implements Interceptor {
public Object intercept(Invocation iv) throws Throwable {
BoundSql boundSql = ((StatementHandler)iv.getTarget()).getBoundSql();
System.out.println("SQL: " + boundSql.getSql());
return iv.proceed();
}
}
注意事项:
- 生产环境需关闭敏感SQL日志防止数据泄露
- 复杂参数类型(如Blob)可能无法准确还原
- 推荐开发环境使用MyBatis Log Ultra等专业工具