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就更便捷了。java