如何查看Java应用中createNativeQuery实际发送的SQL语句
如何查看JPA NativeQuery实际执行的SQL语句
我们有一套基于Java构建的系统,支持自定义JavaScript宏,底层使用Java实体,但我完全没有Java相关经验。当前SQL执行异常,在PHP中我会用var_dump查看最终生成的SQL语句,想了解是否有办法查看getEntityManager().createNativeQuery(sqlStr)实际发送给数据库的内容。
相关代码如下:
function insertTempHeaderRecord(filereadid, lineArray){ try{ var sqlStr="INSERT INTO vl_edisalesorder (filereadid, edifilename, customerid, deladdressid, contactid, " "pricelistid, customerref, orderdate, delivercontact, delivertelephone, taillift, bookdelivery, deliveryins, orderid "+" VALUES (:param0, :param1, :param2, :param3, :param4, :param5, :param6, :param7, :param8, :param9, :param10, :param11, :param12, :param13) "; getEntityManager().createNativeQuery(sqlStr) .setParameter("param0", filereadid) .setParameter("param1", filereadid) .setParameter("param2", trimTo(lineArray[3],10)) //traderid .setParameter("param3", trimTo(lineArray[4], 10)) //deladd .setParameter("param4", trimTo(lineArray[5],10)) //contactid .setParameter("param5", "0536") .setParameter("param6", trimTo(lineArray[2],25)) //custref .setParameter("param7", Packages.java.sql.Date(orderdate.getTime())) .setParameter("param8", trimTo(lineArray[8],25)) //delcontact .setParameter("param9", trimTo(lineArray[6],20)) //deltel .setParameter("param10", importer.Boolean.valueOf(lineArray[9])) //tlrq .setParameter("param11", importer.Boolean.valueOf(lineArray[10])) //delbook .setParameter("param12", trimTo(lineArray[7],30)) //delinstr .setParameter("param13", importer.Boolean.valueOf(lineArray[10])) //delivery book in .executeUpdate(); }catch(err){ return false; } return true; logger.info("Petestestworkflow.xml - this worked ok"); }
先提个明显的问题:你的SQL语法有误
注意看sqlStr里的列名部分,最后一个列orderid后面缺少闭合的右括号,正确的写法应该是:
var sqlStr="INSERT INTO vl_edisalesorder (filereadid, edifilename, customerid, deladdressid, contactid, " "pricelistid, customerref, orderdate, delivercontact, delivertelephone, taillift, bookdelivery, deliveryins, orderid) "+" VALUES (:param0, :param1, :param2, :param3, :param4, :param5, :param6, :param7, :param8, :param9, :param10, :param11, :param12, :param13) ";
这个语法错误大概率是导致执行异常的直接原因。
查看实际执行SQL的方法
1. 手动拼接参数生成调试SQL(最简单直接)
在JS宏里,你可以把参数值手动替换到SQL模板里,然后用logger.info()打印出来,就像PHP里的var_dump:
// 在executeUpdate()之前添加这段调试代码 var debugSql = sqlStr .replace(":param0", filereadid) .replace(":param1", filereadid) .replace(":param2", "'" + trimTo(lineArray[3],10) + "'") // 字符串类型要加单引号 .replace(":param3", "'" + trimTo(lineArray[4],10) + "'") .replace(":param4", "'" + trimTo(lineArray[5],10) + "'") .replace(":param5", "'0536'") .replace(":param6", "'" + trimTo(lineArray[2],25) + "'") .replace(":param7", "'" + Packages.java.sql.Date(orderdate.getTime()) + "'") // 日期转字符串加单引号 .replace(":param8", "'" + trimTo(lineArray[8],25) + "'") .replace(":param9", "'" + trimTo(lineArray[6],20) + "'") .replace(":param10", importer.Boolean.valueOf(lineArray[9]) ? 1 : 0) // 布尔值转数据库识别的0/1 .replace(":param11", importer.Boolean.valueOf(lineArray[10]) ? 1 : 0) .replace(":param12", "'" + trimTo(lineArray[7],30) + "'") .replace(":param13", importer.Boolean.valueOf(lineArray[10]) ? 1 : 0); logger.info("调试用SQL:" + debugSql);
打印后你就能直接看到完整的SQL,复制到数据库客户端里执行,就能快速排查问题。
2. 开启JPA的SQL日志输出
如果系统用的是Hibernate(绝大多数JPA实现都是),可以通过修改系统日志配置,开启SQL和参数的日志:
- 将
org.hibernate.SQL的日志级别设为DEBUG,会输出执行的SQL语句 - 将
org.hibernate.type.descriptor.sql.BasicBinder设为TRACE,会输出参数绑定的具体值
不过这个方法需要你能修改系统的日志配置文件,如果权限不允许就用不了。
3. 利用JPA Query的unwrap方法(依赖系统实现)
部分JPA实现允许将NativeQuery转换为底层的具体类,比如Hibernate的NativeQueryImpl,然后获取SQL:
// 参数设置完成后,添加这段代码 var query = getEntityManager().createNativeQuery(sqlStr) .setParameter("param0", filereadid) // ... 所有参数设置 ... try { var hibernateQuery = query.unwrap(Packages.org.hibernate.query.NativeQuery.class); logger.info("执行的SQL:" + hibernateQuery.getQueryString()); } catch(e) { logger.info("无法获取SQL,可能系统不支持该方法"); }
这个方法不一定适用于所有系统,如果报错就换第一种方法。
内容的提问来源于stack exchange,提问作者Pete North
相关产品推荐
相关产品推荐

