如何使用带有命名参数的语句构建一个带有值的SQL字符串?

时间:2014-10-20 20:14:31

标签: java sql prepared-statement named-parameters

我正在寻找一个实用程序来准备一个带有命名参数和值的SQL语句,但不执行它。我只是希望生成的SQL语句(将值替换为named params)作为java.lang.String对象。我在Spring或Apache Commons中找不到任何东西。 [我知道如何为java.sql启用调试日志记录。*]因为我在大型机上查询数据库实例,所以不允许使用预处理语句;由于一些奇怪的原因,支持已被禁用。这个决定超出了我的控制或影响范围。你知道一个可以帮助我的实用工具吗?如果必须的话,我想我可以自己动手,但我不愿意。

2 个答案:

答案 0 :(得分:0)

首先,您应该知道准备好的声明的原因之一是安全性。简单地用参数的文本表示替换占位符然后发送简单字符串的自然方式是导致许多SQL注入攻击的原因。一个经典的例子是

SELECT * FROM tab WHERE tabid = ?

参数1; DELETE FROM tab 参数的文本替换,您可以在delete all语句中转换简单查询。当然,真正的攻击可能比那更聪明......

实际上很奇怪在大型机数据库中,人们建议使用预处理语句的纯SQL语句。根据我的经验,安全理由导致了相反的规则。你应该问这个原因,以及推荐的方法是什么。它可能是使用特殊的库,或框架或...但如果可以,请避免文本替换。

编辑:

如果您真的遇到了文本替换问题,则必须使用自己的实用程序。如上所述,我无法想象一个框架会这样做。在真正的单词应用程序中,可以合理地确定是否可以验证所有输入以避免SQL注入的任何可能性(没有特殊字符或仅在已知位置)。但是,如果我在你的位置,我不会尝试模仿SQL预处理语句,我只会使用String.format,其中格式字符串将是Formatter语法中带占位符的SQL查询。

答案 1 :(得分:0)

这就像是说你希望看到你的Java代码将用户的输入硬编码到源代码中。

这将是荒谬的,因为您知道用户的输入永远不会与Java源相结合。它在运行时与编译的 Java应用程序结合(可以这么说)。输入数据永远不会合并到源中。

它与准备好的SQL语句的方式相同。

在prepare()期间,RDBMS接收文本SQL字符串,并在内部对其进行解析并保留一种"字节码"查询的版本。在此内部表示中,将记录参数占位符,并且在提供值之前无法执行查询。

在execute()期间,RDBMS接收参数值,并将它们与字节码组合。参数永远不会看到原始的SQL文本!这就是它的工作方式。