我正在QueryBuilder为带有postgresql DB的Web应用程序的家庭滚动类做最后的修饰。它PreparedStatement用于所有查询,并且可以防止SQL注入。
QueryBuilder
PreparedStatement
但是,我想要一种“快速而肮脏的”方式来表示QueryBuilder其toString()方法,仅用于调试目的。该方法将按通常传递给的方式组装查询字符串PreparedStatement,然后只需将?字符串中的每个字符串替换为其相应的单引号值即可。该toString()Javadoc将警告其他开发者,这是一个不安全的近似仅用于调试,等等等等。
toString()
?
我知道这些值应将其单引号加倍(即O'Connell转义为O''Connell)。还有其他我要忘记的特殊字符吗?我寻找类似的问题,但只发现人们被责骂使用PreparedStatement(他们应该这样做,让记录显示)。
O'Connell
O''Connell
编辑: 不希望针对此特定任务使用第三方工具,我真的只想在这里快速又脏。我确实很喜欢这些链接-我可能会考虑将它们用于其他用途。
最后编辑: 感谢所有有用的指示。我只想补充一下,对于那些从Google跌跌撞撞来到这里的人,请 不要 将这些技巧用于任何触及数据库的东西,请使用PreparedStatement。
对于“快速而肮脏的”转义,加倍撇号就足够了。但是,请注意字符串文字中已经存在的问号:
SELECT column FROM table WHERE column = 'A question?' or column = ?
您不想替换第一个问号。此外,这些极端情况还应注意:
SELECT /* Is this a comment?? */ * FROM table -- -- -- Another comment?? WHERE column = ?
该语句中只有一个绑定值。但是,对于不太快捷的解决方案,您可以使用jOOQ之类的库来解决此问题(免责声明:我为jOOQ背后的公司工作)。它将为您进行内联,也将为更讨厌的数据类型做内联:
DSLContext ctx = DSL.using(SQLDialect.POSTGRES); Object[] bindValues = { 1, "a'bc", Date.valueOf("2012-09-24"), "xy".getBytes() }; String string = ctx.query( "SELECT 1 WHERE A = ? AND B = ? AND C = ? AND D = ?", bindValues).toString();
以上将呈现
SELECT 1 WHERE A = 1 AND B = 'a''bc' AND C = date '2012-09-24' AND D = E'\\170\\171::bytea