咱們作過的不少項目中都會使用spring的JdbcTemplate進行結果集的查詢操做,之前在使用的時候一直都是「拿來主義」,功能實現了就OK了,沒有深究什麼內容,特別是查詢接口的回調內容方法,沒有過多的研究過細節內容。最近一次使用JdbcTemplate進行查詢操做,發現了一些有規律的內容,因此就深刻學習了一下。和你們一塊兒探討一下:spring
對於spring的JdbcTemplate進行結果集查詢操做,spring給咱們開發的是一系列的query方法,這些查詢的方法中回調的接口主有三種:ResultSetExtractor,RowCallbackHandler,RowMapper,這個內容有圖有真相:數據庫
可是這三種回調接口具體的用法和區別,咱們一塊兒來看一下:app
場景設定,數據庫中存在T_USER表,表中存在多條數據,須要將是表中數據映射到User對象上less
一、org.springframework.jdbc.core.ResultSetExtractoride
ResultSetExtractor接口中定義的方法以下:學習
public interface ResultSetExtractor { Object extractData(ResultSet rs) throws SQLException, DataAccessException; }
若是使用ResultSetExtractor接口做爲回調方法,查詢方式以下:ui
List<User> userList = (List<User>)jdbcDao.getJdbcTemplate(). query("select * from T_USER", new ResultSetExtractor() { @Override public Object extractData(ResultSet rs) throws SQLException, DataAccessException { List<User> userList = new ArrayList<User>(); while (rs.next()) { User user = new User(); user.setId(rs.getInt("N_ID")); user.setName(rs.getString("C_NAME")); userList.add(user); } return userList; } });
二、org.springframework.jdbc.core.RowCallbackHandleridea
RowCallbackHandler接口中定義的方法以下:code
public interface RowCallbackHandler { void processRow(ResultSet rs) throws SQLException; }
若是使用RowCallbackHandler接口做爲回調方法,查詢方式以下:對象
final List<User> userList = new ArrayList<User>(); jdbcDao.getJdbcTemplate().query("select * from T_USER", new RowCallbackHandler(){ @Override public void processRow(ResultSet rs) throws SQLException { User user = new User(); user.setId(rs.getInt("N_ID")); user.setName(rs.getString("C_NAME")); userList.add(user); } });
三、org.springframework.jdbc.core.RowMapper
RowMapper接口中定義的方法以下:
public interface RowMapper { Object mapRow(ResultSet rs, int rowNum) throws SQLException; }
若是使用RowMapper接口做爲回調方法,查詢方式以下:
List<User> userList = (List<User>)jdbcDao.getJdbcTemplate(). query("select * from T_USER", new RowMapper(){ @Override public Object mapRow(ResultSet rs, int rowNumber) throws SQLException { User user = new User(); user.setId(rs.getInt("N_ID")); user.setName(rs.getString("C_NAME")); return user; } });
經過以上的例子咱們能夠看出,使用三種回調接口主要的區別是:
一、使用三種Callback接口做爲參數的query方法的返回值不一樣:
以ResultSetExtractor做爲方法參數的query方法返回Object型結果,要使用查詢結果,咱們須要對其進行強制轉型;
以RowMapper接口做爲方法參數的query方法直接返回List型的結果;
以RowCallbackHandler做爲方法參數的query方法,返回值爲void;
二、使用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的文檔描述咱們能夠知道:
一、RowMapper應該就是一個精簡版的ResultSetExtractor,RowMapper可以直接處理一條結果集內容,而ResultSetExtractor須要咱們本身去ResultSet中去取結果集的內容,可是ResultSetExtractor擁有更多的控制權,在使用上能夠更靈活;
二、與RowCallbackHandler相比,ResultSetExtractor是無狀態的,他不可以用來處理有狀態的資源。
備註:在spring3中,這三個接口的內容也作出了修改,其中:ResultSetExtractor和RowMapper開始支持泛型,返回值的內容也是泛型中的對象,而RowCallbackHandler沒有作出任何修改。