利用JDBC的PrepareStatement打印真实SQL的方法详解
前言
本文主要给大家介绍了关于利用JDBC的PrepareStatement打印真实SQL的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍:
我们知道,JDBC的PrepareStatement优点多多,通常都是推荐使用PrepareStatement而不是其基类Statment。PrepareStatement支持?占位符,可以将参数按照类型转自动换为真实的值。既然这一过程是自动的,封装在JDBC内部的,那么我们外部就不得而知目标的SQL最终生成怎么样——于是在调试过程中便有一个打印SQL的问题。我们对PrepareStatement传入SQL语句,如SELECT*FROMtableWHEREid=?,然后我们传入对应的id参数,假设是id=10,那怎么把得到参数的SELECT*FROMtableWHEREid= 12结果完整地得出来呢?——这便是本文所要探讨的问题。下面话不多说了,来一起看看详细的介绍:
方法如下:
首先,我们看看典型的一个PrepareStatement调用方法,如下一个函数,
/** *查询单个结果,保存为Map结构。如果查询不到任何数据返回null。 * *@paramconn *数据库连接对象 *@paramsql *SQL语句,可以带有?的占位符 *@paramparams *插入到SQL中的参数,可单个可多个可不填 *@returnMap 结构的结果。如果查询不到任何数据返回null。 */ publicstaticMap query(Connectionconn,Stringsql,Object...params){ Map map=null; printRealSql(sql,params);//打印真实SQL的函数 try(PreparedStatementps=conn.prepareStatement(sql);){ if(params!=null) for(inti=0;i 值得注意该函数里面:
printRealSql(sql,params);//打印真实SQL的函数其参数一sql就是类似SELECT*FROMtableWHEREid=?的语句,参数二params为Object...params的参数列表,可以是任意类似的合法SQL值。最后,通过printRealSql函数最终得出形如SELECT*FROMtableWHEREid= 12的结果。
printRealSql函数源码如下:
/** *在开发过程,SQL语句有可能写错,如果能把运行时出错的SQL语句直接打印出来,那对排错非常方便,因为其可以直接拷贝到数据库客户端进行调试。 * *@paramsql *SQL语句,可以带有?的占位符 *@paramparams *插入到SQL中的参数,可单个可多个可不填 *@return实际sql语句 */ publicstaticStringprintRealSql(Stringsql,Object[]params){ if(params==null||params.length==0){ LOGGER.info("TheSQLis------------>\n"+sql); returnsql; } if(!match(sql,params)){ LOGGER.info("SQL语句中的占位符与参数个数不匹配。SQL:"+sql); returnnull; } intcols=params.length; Object[]values=newObject[cols]; System.arraycopy(params,0,values,0,cols); for(inti=0;i\n"+statement); ConnectionMgr.addSql(statement);//用来保存日志 returnstatement; } /** *?和参数的实际个数是否匹配 * *@paramsql *SQL语句,可以带有?的占位符 *@paramparams *插入到SQL中的参数,可单个可多个可不填 *@returntrue表示为?和参数的实际个数匹配 */ privatestaticbooleanmatch(Stringsql,Object[]params){ if(params==null||params.length==0)returntrue;//没有参数,完整输出 Matcherm=Pattern.compile("(\\?)").matcher(sql); intcount=0; while(m.find()){ count++; } returncount==params.length; } 可见,上述思路是非常简单的,——有多少个?占位符,就要求有多少个参数,然后一一对照填入(数组)。match函数会检查第一个步骤,检查个数是否匹配,否则会返回“SQL语句中的占位符与参数个数不匹配”的提示;然后,参数的值会被转换为符合SQL值所要求的类型;最后,就是将SQL一一填入,——此处使用了一个字符串的技巧,先把?字符通通转换为%s,——那是String.format可识别的占位符,如此再传入Object[]参数列表,即可得出我们期待的SQL结果。
我们不能保证那SQL可以直接放到数据库中被解析。因为我们的初衷只是把SQL打印出来,务求更近一步让程序员在开发阶段看到SQL是怎么样子的,而且不是一堆?、?……,这样会显得更符合真实情形一点。
PrepareStatement内部源码肯定有这一步骤或者某个变量是表示那个真实SQL的,——只是没有暴露出来。如果有,那么对程序员会更友好一些。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。