如何在Spring JDBCTemplate中正确使用预处理语句?

6

我需要在一个数据库中执行一次查询操作,这个操作我会经常使用。使用普通语句时,它完全正常:

 List<Invoice> l = this.jdbcTemplate.query(
                     "SELECT id, name, stuff FROM example WHERE amount > ?",
                     new Object[] { "100" }, new RowMapper<Invoice>() {...} );

我经常执行上述语句,为了提高性能,我希望使用预处理语句。但是,我现在不确定如何正确地使用Spring API来实现这一点。
我很困惑为什么Spring要求我在查询时传递一个PreparedStatementCreator实例作为参数?我认为这正是我不需要每次使用查询方法都创建新的预处理语句的关键所在。因此,以下代码片段将完全没有意义,因为每次调用query方法时都会创建新的预处理语句:
 List<Invoice> l = this.jdbcTemplate.query(
                     new PreparedStatementCreator() {
                         String query = "SELECT id, name, stuff FROM example WHERE amount > ?";
                         public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                              return connection.prepareStatement(query);
                         }
                     },
                     new PreparedStatementSetter() {...}, 
                     new RowMapper<Invoice>() {...} );

我需要创建自己的ReusablePreparedStatementCreator吗?这将只在第一次调用createPreparedStatement时创建一个新方法。

PreparedStatementCreatorFactory可以帮助我吗?

换句话说,如何正确地创建一个使用准备好的语句的选择查询,在Spring JDBCTemplate中获得性能优势,同时不失去RowMapper的优势?


Spring已经使用了PreparedStatement,所以不需要让它变得更加复杂。 - M. Deinum
1
@M.Deinum,您是否有官方参考资料支持这个说法?我简要查看了JdbcTemplate :: query(final String sql,final ResultSetExtractor <T> rse)的代码,但没有发现任何迹象表明这是正确的。 - leo
请参阅 https://github.com/spring-projects/spring-framework/blob/master/spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java#L1557,这是在使用其中一个 query 方法时使用的内部类。是否获取新语句取决于您的 JDBC 驱动程序以及它是否缓存语句。 - M. Deinum
@M.Deinum 谢谢!但在这种情况下,每次调用查询方法都会创建一个新的 PreparedStatement 对象。我可能错了,但我认为这并没有给我带来我想要实现的改进。 - leo
2
这取决于您的JDBC提供程序是否被缓存(因此可以重复使用)或者是否创建一个新的。另外,我怀疑您是否想要缓存PreparedStatement,因为您将如何为下一个连接执行它?(基本上每个事务都在自己的连接上运行)。 - M. Deinum
1个回答

10

首先,我不确定每次不重新创建预编译语句是否会显著提高性能,因为JDBC驱动程序/数据库通常会缓存预编译语句。

但是,如果您想使用单个预编译语句执行多个查询,只需使用JdbcTemplate的一个execute()方法,该方法从SQL查询创建预编译语句(或允许您创建它),然后执行以预编译语句作为参数的回调函数。您可以在此回调函数中循环,并执行任意次数的语句。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接