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

141 篇文章 6 订阅
73 篇文章 3 订阅

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

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


 

 

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

 

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

1、org.springframework.jdbc.core.ResultSetExtractor

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

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

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

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

 

2、org.springframework.jdbc.core.RowCallbackHandler

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

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

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

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

3、org.springframework.jdbc.core.RowMapper

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

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

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

  1. List<User> userList = jdbcDao.getJdbcTemplate().  
  2.                                    query("select * from T_USER"new RowMapper<User>(){  //注意这里泛型不是List
  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接口作为方法的参数:
                   extractData方法是把ResultSet对应后,需要我们
    手动迭代封装成List<T>,再返回;(需要我们指定泛型T
  • 以RowMapper接口作为方法的参数:
                   mapRow方法是把ResultSet对应后,结果T会被Spring
    自动封装成List<T>,再返回;(需要我们指定泛型T
  • 以RowCallbackHandler作为方法参数的(这个方法不常用,所以放最后说。和ResultSetExtractor结构很相似):
                   processRow方法是把ResultSet对应后,也需要我们
    手动迭代封装成List<T>,但是返回值为void,所以需要我们在query方法外用List<T>来接收processRow中封装的List<T>;

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值