日期:2014-05-16  浏览次数:20612 次

JdbcTemplate查询数据 三种callback之间的区别(转)
JdbcTemplate针对数据查询提供了多个重载的模板方法,你可以根据需要选用不同的模板方法。 如果你的查询很简单,仅仅是传入相应SQL或者相关参数,然后取得一个单一的结果,那么你可以选择如下一组便利的模板方法:

int queryForInt(String sql)

int queryForInt(String sql, Object[] args)

long queryForLong(String sql)

long queryForLong(String sql, Object[] args)

Object queryForObject(String sql, Class requiredType)

Object queryForObject(String sql, Object[] args, Class requiredType)

Map queryForMap(String sql)

Map queryForMap(String sql, Object[] args)

比如说,你所查询的结果就包含一列数字型的结果,或者使用了SQL函数,或者其他单列的结果,我们就可以直接通过这组便利的模板方法进行查询:
int age = jdbcTemplate.queryForInt("select age from customer where customerId=?",new Object[]{new Integer(100)});
...
long interval = jdbcTemplate.queryForLong("select count(customerId) from customer");
...
String customerName = jdbcTemplate.queryForString("select username from customer where customerId=110");
...
Map singleCustomer = jdbcTemplate.queryForMap("select * from customer limit 1");
...
queryForMap方法与其他方法不同之处在于,它的查询结果以java.util.Map的形式返回,Map的key对应所查询表的列名,Map的value当然就是对应key所在列的值啦。 当然了,你也看到了,这组模板方法主要用于单一结果的查询,使用的时候也请确保你的SQL查询所返回的结果是单一的,否则,JdbcTemplate将抛出org.springframework.dao.IncorrectResultSizeDataAccessException异常。
如果查询的结果将返回多行,而你又不在乎他们是否拥有较强的类型约束,那么,以下模板方法可以帮助你:

List queryForList(String sql)

List queryForList(String sql, Object[] args)

queryForList方法根据传入的SQL以及相应的参数执行查询,将查询的结果以java.util.List的形式返回,返回的java.util.List中的每一个元素都是java.util.Map类型,分别对应结果集中的一行,Map的Key为每一列的列名,而Map的值就是当前行列名对应的值。
好啦,如果这些还不足以满足你的查询需要,那么我们就更进一步,使用相应的Callback接口对查询结果的返回进行定制吧!

用于查询的回调接口定义主要有以下三种:

org.springframework.jdbc.core.ResultSetExtractor.  基本上属于JdbcTemplate内部使用的Callback接口,相对于下面两个Callback接口来说,ResultSetExtractor拥有更多的控制权,因为使用它,你需要自行处理ResultSet:

public interface ResultSetExtractor
{
Object extractData(ResultSet rs) throws SQLException, DataAccessException;
}
在直接处理完ResultSet之后,你可以将处理后的结果以任何你想要的形式包装后返回。
org.springframework.jdbc.core.RowCallbackHandler.  RowCallbackHandler相对于ResultSetExtractor来说,仅仅关注单行结果的处理,处理后的结果可以根据需要存放到当前RowCallbackHandler对象内或者使用JdbcTemplate的程序上下文中,当然,这个完全是看个人爱好了。 RowCallbackHandler的定义如下:

public interface RowCallbackHandler
{
void processRow(ResultSet rs) throws SQLException;
}
org.springframework.jdbc.core.RowMapper.  ResultSetExtractor的精简版,功能类似于RowCallbackHandler,也只关注处理单行的结果,不过,处理后的结果会由ResultSetExtractor实现类进行组合。 RowMapper的接口定义如下:

public interface RowMapper
{
Object mapRow(ResultSet rs, int rowNum) throws SQLException;
}
为了说明这三种Callback接口的使用和相互之间的区别,我们暂且设定如下场景:
数据库表customer中存在多行信息,对该表查询后,我们需要将每一行的顾客信息都映射到域对象Customer中,并以java.util.List的形式返回所有的查询结果。

现在,我们分别使用这三种Callback接口对customer表进行查询:

List customerList = (List)jdbcTemplate.query("select * from customer", new ResultSetExtractor(){

public Object extractData(ResultSet rs) throws SQLException,DataAccessException
{
List customers = new ArrayList();
while(rs.next())
{
Customer customer = new Customer();
customer.setFirstName(rs.getString(1));
customer.setLastName(rs.getString(2));
...
customers.add(customer);
}
return customers;
}});
List customerList = jdbcTemplate.query("select * from customer", new RowMapper(){

public Object mapRow(ResultSet rs, int rowNumber) throws SQLException {
Customer customer = new Customer();
customer.setFirstName(rs.getString(1));
customer.setLastName(rs.getString(2));
...
return customer;
}});
final List customerList = new ArrayList();

jdbcTemplate.query("select * from customer", new RowCallbackHandler(){

public void processRow(ResultSet rs) throws SQLException {
Customer customer = new Customer();
customer.setFirs