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;
}
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 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;
Customer customer = new Customer();
customer.setFirstName(rs.getString(1));
customer.setLastName(rs.getString(2));
...
return customer;
}});
final List customerList = new ArrayList();
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
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之後,你可以將處理後的結果以任何你想要的形式包裝後返回。
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的callbackJDBC
- 查詢兩個日期之間的資料
- BI、資料倉儲和資料分析之間的區別
- 日期區間查詢
- MySql、SqlServer、Oracle 三種資料庫查詢分頁方式MySqlServerOracle資料庫
- Redis 三種特殊資料型別之 BitmapsRedis資料型別
- python不同資料型別之間的區別有什麼?Python資料型別
- hibernate的三種查詢方式
- Apache Spark:資料框,資料集和RDD之間的區別 - BaeldungApacheSpark
- MongoDB之資料查詢(資料排序)MongoDB排序
- Oracle查詢100萬到200萬之間的資料Oracle
- 樹狀陣列的區間查詢與區間修改陣列
- MySql中的資料查詢語言(DQL)三:連線查詢MySql
- MongoDB之資料查詢操作MongoDB
- 物件點查詢和中括號查詢的區別物件
- MySQL之資料的簡單查詢MySql
- Laravel MongoDB 時間區間查詢的問題LaravelMongoDB
- Redis 三種特殊資料型別之 HyperloglogRedis資料型別
- 大資料分析與機器學習之間的區別與聯絡大資料機器學習
- 資料更改事件的三種型別事件型別
- 在資料庫的查詢與更新中,CHARINDEX與instr的區別?資料庫Index
- 資料庫資料的查詢----連線查詢資料庫
- ORACLE資料庫遞迴查詢時間區間,可傳入指定日期Oracle資料庫遞迴
- mysql查詢最近時間的一組資料MySql
- 關於Oracle資料庫的時間查詢Oracle資料庫
- 查詢某時間段的統計資料
- 【樹狀陣列 區間更新區間查詢】code陣列
- 【clickhouse專欄】資料庫、資料倉儲之間的區別與聯絡資料庫
- MongoDB之資料查詢(陣列)MongoDB陣列
- 資料庫學習(三)基本查詢資料庫
- 資料結構之三大查詢資料結構
- 三種連結方式的區別
- Hibernate通常是三種:hql查詢,QBC查詢和QBE查詢:
- MySQL(三) 資料庫表的查詢操作【重要】MySql資料庫
- Mysql兩種主要資料引擎的區別MySql
- Redis 三種特殊資料型別Redis資料型別
- 上億級別資料庫查詢資料庫
- Redis 中三種特殊的資料型別Redis資料型別