繁体   English   中英

准备好的语句中的串联

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM