我的 Java (JDK6) 项目使用Spring和JDBCTemplate进行所有数据库访问。我们最近从 Spring 2.5 升级到 Spring 3 (RC1)。该项目不使用像Hibernate或EJB这样的 ORM 。
如果我需要读取一堆记录,并对它们进行一些内部处理,似乎有几种(重载)方法:query、queryForList 和 queryForRowSet
使用一个而不是另一个的标准应该是什么?有性能差异吗?最佳实践?
您能否推荐一些外部参考资料以进一步研究该主题?
我的 Java (JDK6) 项目使用Spring和JDBCTemplate进行所有数据库访问。我们最近从 Spring 2.5 升级到 Spring 3 (RC1)。该项目不使用像Hibernate或EJB这样的 ORM 。
如果我需要读取一堆记录,并对它们进行一些内部处理,似乎有几种(重载)方法:query、queryForList 和 queryForRowSet
使用一个而不是另一个的标准应该是什么?有性能差异吗?最佳实践?
您能否推荐一些外部参考资料以进一步研究该主题?
我发现作为列表访问的标准方法是通过query()
方法而不是任何其他方法。与其他方法的主要区别在于query
您必须实现一个回调接口(RowMapper
、RowCallbackHandler
或ResultSetExtractor
)来处理您的结果集。
ARowMapper
可能是您发现自己大部分时间都在使用的。当结果集的每一行对应于列表中的一个对象时使用它。您只需要实现一个方法来mapRow
填充行中的对象类型并返回它。Spring还有一个BeanPropertyRowMapper
可以通过将bean属性名称与列名称匹配来填充列表中的对象(注意这个类是为了方便而不是性能)。
RowCallbackHandler
当您需要您的结果不仅仅是一个简单的列表时,A会更有用。您必须自己管理使用此方法的返回对象。当我需要一个映射结构作为我的返回类型时(即用于树表的分组数据,或者如果我正在创建基于主键的自定义缓存),我通常会发现自己使用它。
ResultSetExtractor
当您想要控制结果的迭代时使用A。您实现了一个方法extractData
,该方法将作为调用的返回值query
。如果我必须构建一些使用其他回调接口来构建更复杂的自定义数据结构,我只会发现自己使用它。
这些queryForList()
方法很有价值,因为您不必实现这些回调方法。有两种方式使用 queryForList。第一个是如果您只从数据库中查询单个列(例如字符串列表),您可以使用将 Class 作为参数的方法的版本自动为您提供这些类的唯一对象列表.
调用其他实现时,queryForList()
您将得到一个列表,其中每个条目都是每列的映射。虽然这很好,因为您节省了编写回调方法的费用,但处理这种数据结构相当笨拙。你会发现自己做了很多转换,因为地图的值是 type Object
。
我实际上从未见过queryForRowSet
在野外使用的方法。这会将查询的整个结果加载到CachedRowSet
由 Spring SqlRowSet 交换的对象中。我看到使用这个对象的一个很大的缺点是,如果您将SqlRowSet
周围传递到应用程序的其他层,您会将这些层耦合到您的数据访问实现。
除了我提到的BeanPropertyRowMapper
. 如果您正在对大型结果集进行一些复杂的操作,您可能能够通过ResultSetExtractor
为您的特定情况编写优化来获得一些性能提升。
如果您想了解更多信息,我会查阅Spring JDBC 文档和我提到的类的 JavaDoc。您还可以查看一些有关 Spring Framework 的书籍。虽然它有点过时了Java Development with the Spring Framework有一个关于使用 JDBC 框架的非常好的部分。最重要的是,我想说只是尝试用每种方法编写一些代码,看看哪种方法最适合你。
既然你在美妙的泛型领域,你可能真正想做的是使用SimpleJdbcTemplate
和使用它的query()
方法用于Lists
对象和queryForObject()
单个对象。原因很简单,它们比JdbcTemplate
.
对上述出色答案的一个小补充:如果您正在运行一个简单的查询并期望单行,其他方法,如 queryForInt、queryForLong、queryForMap、queryForObject 等,有时可能看起来是不错的选择。
但是,如果您可以返回 0 或 1 行,则 queryForList 方法通常更容易,否则您必须捕获 IncorrectResultSizeDataAccessException。我很难学到这一点。