[英]Concatenation in prepared statement
我已经为mySQL编写了通用DAO层(它可以使用Reflection和ResultSetMetaData保存/获取将Entity扩展到表中的任何类对象)。 我的实现在sql查询中几乎没有串联。 是浪费了准备好的语句的所有优点,还是我只是失去了连接String的性能,仅此而已?
例如,用于实体删除的一段代码:
PreparedStatement prepStatement = con.prepareStatement("DELETE FROM "
+ tableName + " WHERE id = ?");
prepStatement.setLong(1, id);
PreparedStatement
的主要好处是,当您的代码的行为与此伪代码类似时:
PreparedStatement ps = con.prepareStatement("blabalblabla");
for (int i = 0; i < a gazillion times; i++) {
// Set parameters into ps
...
// execute already prepared statement
ps.execute();
}
也就是说,您准备一次并执行多次 ,每次使用不同的参数集。 这使驱动程序/数据库仅执行一次可能耗资巨大的操作(例如解析),然后重新使用该工作。 除此之外,使用PreparedStatement
可以解释为对驱动程序的提示,因为它应该缓存该语句资源或某些东西,因为它将在以后使用,但是我认为它的影响不会像“准备一次”那样大。执行许多”方法。
您使用串联添加表名不会禁用JDBC驱动程序所做的优化(如果有)。 但是无论如何,如果您的代码“一次执行一次准备”比“一次执行多次准备”更多,那么PreparedStatement可能只具有次要的性能优势。
请注意,以上所有都是高度依赖数据库/驱动程序的。 例如,Oracle,如果您使用执行好很多 PreparedStatement
在我所描述的“准备执行一次多”的方式秒。 最后一条建议是,出于性能和安全性的考虑,除非没有其他选择,否则不要忘记连接参数值。
建议使用准备好的语句来提高数据库性能。 理论上,数据库驱动程序会缓存准备好的语句(您可能需要启用对连接对象的缓存)。 我认为串联不是那么关键。 请记住,tableName在驱动程序缓存中可能区分大小写。
我将检查您的数据库驱动程序功能,并且您应该能够调试驱动程序,并监视数据库以查看如何处理/执行语句。
您的示例中的变量tableName可能会引入SQL注入漏洞,但它可能是防止这种情况的另一种方法。 例如,
Map<String,String> myTables; // key and value are the same.
tableName = myTables.get(tableName); // safe known value or null.
通常,最好始终使用准备好的语句以避免麻烦。 但是,有时“即时”构建查询(通常是where
查询中的大多数where
)可以节省许多行,否则会接近重复的代码,因此很难说“从不这样做”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.