JdbcTemplate查询数据 三种callback之间的区别(ResultSetExtractor,RowMapperRowCallbackHandler)
http://liangfeng366.iteye.com/blog/836077
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.setFirstName(rs.getString(1));
customer.setLastName(rs.getString(2));
...
customerList.add(customer);
}});
如果你沒有發現最大的差異在哪里,那么容我細表:
使用三種Callback接口作為參數的query方法的返回值不同:
以ResultSetExtractor作為方法參數的query方法返回Object型結果,要使用查詢結果,我們需要對其進行強制轉型;
以RowMapper接口作為方法參數的query方法直接返回List型的結果;
以RowCallbackHandler作為方法參數的query方法,返回值為void;
使用ResultSetExtractor作為Callback接口處理查詢結果,我們需要自己聲明集合類,自己遍歷ResultSet,自己根據每行數據組裝Customer對象,自己將組裝后的Customer對象添加到集合類中,方法最終只負責將組裝完成的集合返回;
使用RowMapper比直接使用ResultSetExtractor要方便的多,只負責處理單行結果就行,現在,我們只需要將單行的結果組裝后返回就行,剩下的工作,全部都是JdbcTemplate內部的事情了。 實際上,JdbcTemplae內部會使用一個ResultSetExtractor實現類來做其余的工作,畢竟,該做的工作還得有人做不是?!
JdbcTemplae內部使用的這個ResultSetExtractor實現類為org.springframework.jdbc.core.RowMapperResultSetExtractor, 它內部持有一個RowMapper實例的引用,當處理結果集的時候,會將單行數據的處理委派給其所持有的RowMapper實例,而其余工作它負責:
public Object extractData(ResultSet rs) throws SQLException {
List results = (this.rowsExpected > 0 ? new ArrayList(this.rowsExpected) : new ArrayList());
int rowNum = 0;
while (rs.next()) {
results.add(this.rowMapper.mapRow(rs, rowNum++));
}
return results;
}
這下應該清楚為啥RowMapper為啥就處理單行結果就能完成ResultSetExtractor頗費周折的工作了吧?!
RowCallbackHandler雖然與RowMapper同是處理單行數據,不過,除了要處理單行結果,它還得負責最終結果的組裝和獲取工作,在這里我們是使用當前上下文聲明的List取得最終查詢結果, 不過,我們也可以單獨聲明一個RowCallbackHandler實現類,在其中聲明相應的集合類,這樣,我們可以通過該RowCallbackHandler實現類取得最終查詢結果:
public class GenericRowCallbackHandler implements RowCallbackHandler {
private List collections = new ArrayList();
public void processRow(ResultSet rs) throws SQLException {
Customer customer = new Customer();
customer.setFirstName(rs.getString(1));
customer.setLastName(rs.getString(2));
...
collections.add(customer);
}
public List getResults()
{
return collections;
}
}
GenericRowCallbackHandler handler = new GenericRowCallbackHandler();
jdbcTemplate.query("select * from customer",handler());
List customerList = handler.getResults();
該使用方式是明了了,不過GenericRowCallbackHandler重用性不佳。
RowCallbackHandler因為也是處理單行數據,所以,總得有人來做遍歷ResultSet的工作,這個人其實也是一個ResultSetExtractor實現類, 它是JdbcTemplate一個內部靜態類,名為RowCallbackHandlerResultSetExtractor,一看它的定義你就知道奧秘之所在了:
private static class RowCallbackHandlerResultSetExtractor implements ResultSetExtractor {
private final RowCallbackHandler rch;
public RowCallbackHandlerResultSetExtractor(RowCallbackHandler rch) {
this.rch = rch;
}
public Object extractData(ResultSet rs) throws SQLException {
while (rs.next()) {
this.rch.processRow(rs);
}
return null;
}
}
總的來說,內部工作歸根結底是由ResultSetExtractor做了,RowCallbackHandler和RowMapper只是為了幫助我們簡化使用上的操作而已。 所以,實際使用中,RowCallbackHandler和RowMapper才是我們最常用的選擇。
對于使用JdbcTemplate進行查詢,基本就這些內容了,當然,如果你非要使用基于StatementCallback之類更底層的execute方法的話,那就是你個人說了算啦。 不過,要想知道JdbcTemplate中有關查詢相關模板方法的更多信息,在實際使用中參考JdbcTemplate的javadoc就可以,當然,有IDE就更便捷了。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/congqian1120/archive/2008/01/16/2046311.aspx
總結
以上是生活随笔為你收集整理的JdbcTemplate查询数据 三种callback之间的区别(ResultSetExtractor,RowMapperRowCallbackHandler)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (强烈推荐)无线网络密码破解方法
- 下一篇: Smarty自学笔记