Spring NamedParameterJDBCTemplate重用Prepared Statements

我使用Spring NamedParameterJdbcTemplate从表中获取一些值。 出于某种原因,查询在我的Java应用程序中运行速度非常慢,而不是在SQL Management Studio上运行相同的查询。 我还注意到在分析器中,准备好的语句不会被重用。 如果我多次在我的JAVA应用程序中运行相同的查询,我会看到正在执行的不同预处理语句。 因此,不确定为什么语句不会被重用。 性能是否因为我在查询中使用IN子句而变慢?

这是我的示例java代码

StringBuilder vQuery = new StringBuilder(); vQuery.append(" SELECT SUM(Qty) FROM vDemand"); vQuery.append(" WHERE ProductID = :ProductID"); vQuery.append(" AND [Date] >= :StartDate AND [Date] <= :EndDate"); vQuery.append(" AND CustomerID IN ( :CustomerID )"); MapSqlParameterSource vNamedParameters = new MapSqlParameterSource(); vNamedParameters.addValue("ProductID", aProductID); vNamedParameters.addValue("CustomerID", aCustomerlIDs); vNamedParameters.addValue("StartDate", aDate, Types.TIMESTAMP); vNamedParameters.addValue("EndDate", aDate, Types.TIMESTAMP); int vTotalQuantity = this.getNamedParameterJdbcTemplate().queryForInt(vQuery.toString(), vNamedParameters); return vTotalQuantity; 

查看Spring的NamedParameterJdbcTemplate的源代码,它将您的SQL解析为ParsedSql结构,然后用问号替换您的命名参数,然后构建PreparedStatement并用您的参数填充它。

它缓存ParsedSql条目,但始终构建新的PreparedStatements因此最终不会在JDBC驱动程序级别重用这些条目。

PreparedStatement比常规Statement有两个优点:

  1. 您可以使用方法向SQL添加参数,而不是在SQL查询本身中执行此操作。 通过这种方式,您可以避免SQL注入攻击,并让驱动程序为您进行类型转换。

  2. 正如您所说,可以使用不同的参数调用相同的PreparedStatement ,并且数据库引擎可以重用查询执行计划。

似乎NamedParameterJdbcTemplate可以帮助您获得第一个优势,但对后者没有任何帮助。