准备好的声明中的连接

时间:2014-07-07 20:30:17

标签: java mysql sql jdbc

我已经为mySQL编写了通用的DAO层(它可以使用Reflection和ResultSetMetaData保存\获取任何将Entity扩展到表的类对象)。我的实现在sql查询中几乎没有连接。它是否浪费了预备语句的所有优点,或者我只是松散地连接字符串而没有其他功能?

例如,用于删除实体的代码:

PreparedStatement prepStatement = con.prepareStatement("DELETE FROM "
                                      + tableName + " WHERE id = ?");
prepStatement.setLong(1, id);

3 个答案:

答案 0 :(得分:3)

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可能只有一点性能优势。

请注意,以上所有内容都是高度依赖数据库/驱动程序的。例如,如果您按照我所描述的“准备一次执行多次”的方式使用PreparedStatement,Oracle会更好地执行很多。作为最后一条建议,请不要忘记,除非您没有其他选择,否则应避免连接参数值,因为性能和安全原因。

答案 1 :(得分:1)

建议使用准备好的语句来提高数据库性能。 理论上,DB驱动程序缓存预准备语句(您可能需要在连接对象上启用缓存)。 我认为连接不是那么重要。 请记住,tableName在驱动程序缓存中可能区分大小写。

我会检查您的数据库驱动程序功能,您应该能够调试驱动程序,并监视数据库以查看语句的处理/执行方式。

答案 2 :(得分:0)

示例中的变量tableName可能会引入SQL注入的漏洞,但它可能是防止这种情况的替代方法。例如,

Map<String,String> myTables; // key and value are the same.
tableName = myTables.get(tableName); // safe known value or null.

通常,最好只是始终使用预先准备好的语句以避免麻烦。但是,有时构建查询(通常是where查询)“动态”可以保存许多行,否则接近重复代码,因此很难说“永远不会这样做”。