使用spring的JdbcTemplate进行查询的三种回调方式的比较

我们做过的很多项目中都会使用spring的JdbcTemplate进行结果集的查询操作,以前在使用的时候一直都是“拿来主义”,功能实现了就OK了,没有深究什么内容,特别是查询接口的回调内容方法,没有过多的研究过细节内容。最近一次使用JdbcTemplate进行查询操作,发现了一些有规律的内容,所以就深入学习了一下。和大家一起探讨一下:

 

对于spring的JdbcTemplate进行结果集查询操作,spring给我们开发的是一系列的query方法,这些查询的方法中回调的接口主有三种:ResultSetExtractorRowCallbackHandlerRowMapper这个内容有图有真相:

使用spring的JdbcTemplate进行查询的三种回调方式的比较
 

但是这三种回调接口具体的用法和区别,我们一起来看一下:

场景设定,数据库中存在T_USER表,表中存在多条数据,需要将是表中数据映射到User对象上

       1、org.springframework.jdbc.core.ResultSetExtractor

     ResultSetExtractor接口中定义的方法如下:

     

Java代码  使用spring的JdbcTemplate进行查询的三种回调方式的比较

  1. public interface ResultSetExtractor {  
  2.        Object extractData(ResultSet rs) throws SQLException,   
  3.                                                 DataAccessException;  
  4.     }  

 

        如果使用ResultSetExtractor接口作为回调方法,查询方式如下:

  

Java代码  使用spring的JdbcTemplate进行查询的三种回调方式的比较

  1. List<User> userList = (List<User>)jdbcDao.getJdbcTemplate().  
  2.                                    query("select * from T_USER"new ResultSetExtractor() {  
  3.             @Override  
  4.             public Object extractData(ResultSet rs) throws SQLException,   
  5.                                                             DataAccessException {  
  6.                  List<User> userList = new ArrayList<User>();  
  7.                  while (rs.next()) {  
  8.                     User user = new User();  
  9.                     user.setId(rs.getInt("N_ID"));  
  10.                     user.setName(rs.getString("C_NAME"));  
  11.                     userList.add(user);  
  12.                  }  
  13.                  return userList;  
  14.             }  
  15.     });  

 

        2、org.springframework.jdbc.core.RowCallbackHandler

              RowCallbackHandler接口中定义的方法如下:

Java代码  使用spring的JdbcTemplate进行查询的三种回调方式的比较

  1. public interface RowCallbackHandler {  
  2.       void processRow(ResultSet rs) throws SQLException;  
  3.   
  4. }  

 

        如果使用RowCallbackHandler接口作为回调方法,查询方式如下:

Java代码  使用spring的JdbcTemplate进行查询的三种回调方式的比较

  1. final List<User> userList = new ArrayList<User>();  
  2.   jdbcDao.getJdbcTemplate().query("select * from T_USER",   
  3.                                                      new RowCallbackHandler(){  
  4.        @Override  
  5.        public void processRow(ResultSet rs) throws SQLException {  
  6.            User user = new User();  
  7.            user.setId(rs.getInt("N_ID"));  
  8.            user.setName(rs.getString("C_NAME"));  
  9.            userList.add(user);  
  10.        }  
  11.    });  

         3、org.springframework.jdbc.core.RowMapper

               RowMapper接口中定义的方法如下:

               

Java代码  使用spring的JdbcTemplate进行查询的三种回调方式的比较

  1. public interface RowMapper {  
  2.         Object mapRow(ResultSet rs, int rowNum) throws SQLException;   
  3. }  

       如果使用RowMapper接口作为回调方法,查询方式如下:

     

Java代码  使用spring的JdbcTemplate进行查询的三种回调方式的比较

  1. List<User> userList = (List<User>)jdbcDao.getJdbcTemplate().  
  2. query("select * from T_USER"new RowMapper(){  
  3.             @Override  
  4.             public Object mapRow(ResultSet rs, int rowNumber)   
  5. throws SQLException {  
  6.                 User user = new User();  
  7.                 user.setId(rs.getInt("N_ID"));  
  8.                 user.setName(rs.getString("C_NAME"));  
  9.                 return user;  
  10.             }  
  11.       });  

 

          通过以上的例子我们可以看出,使用三种回调接口主要的区别是:

         1、使用三种Callback接口作为参数的query方法的返回值不同:

               以ResultSetExtractor作为方法参数的query方法返回Object型结果,要使用查询结果,我们需要对                 其进行强制转型;

               以RowMapper接口作为方法参数的query方法直接返回List型的结果;

               以RowCallbackHandler作为方法参数的query方法,返回值为void;

         2、使用ResultSetExtractor作为Callback接口处理查询结果,我们需要自己声明集合类,自己遍历                        ResultSet,自己根据每行数据组装Customer对象,自己将组装后的Customer对象添加到集合类                    中,方法最终只负责将组装完成的集合返回。

 

        对于这三个回调接口的区别,spring的官方文档给出的说明是这样描述的:

写道

ResultSetExtractor

This interface is mainly used within the JDBC framework itself. A RowMapper is usually a simpler choice for ResultSet processing, mapping one result object per row instead of one result object for the entire ResultSet.
Note: In contrast to a RowCallbackHandler, a ResultSetExtractor object is typically stateless and thus reusable, as long as it doesn't access stateful resources (such as output streams when streaming LOB contents) or keep result state within the object.

RowCallbackHandler

In contrast to a ResultSetExtractor, a RowCallbackHandler object is typically stateful: It keeps the result state within the object, to be available for later inspection. SeeRowCountCallbackHandler for a usage example.
Consider using a RowMapper instead if you need to map exactly one result object per row, assembling them into a List.

RowMapper

Typically used either for JdbcTemplate's query methods or for out parameters of stored procedures. RowMapper objects are typically stateless and thus reusable; they are an ideal choice for implementing row-mapping logic in a single place.
Alternatively, consider subclassing MappingSqlQuery from the jdbc.object package: Instead of working with separate JdbcTemplate and RowMapper objects, you can build executable query objects (containing row-mapping logic) in that style.

 

通过spring的文档描述我们可以知道:

1、RowMapper应该就是一个精简版的ResultSetExtractor,RowMapper能够直接处理一条结果集内容,而ResultSetExtractor需要我们自己去ResultSet中去取结果集的内容,但是ResultSetExtractor拥有更多的控制权,在使用上可以更灵活;

2、与RowCallbackHandler相比,ResultSetExtractor是无状态的,他不能够用来处理有状态的资源。

 

备注:在spring3中,这三个接口的内容也做出了修改,其中:ResultSetExtractor和RowMapper开始支持泛型,返回值的内容也是泛型中的对象,而RowCallbackHandler没有做出任何修改。

 

转载自:https://dzllikelsw-163-com.iteye.com/blog/2038248