一. 前言
最近在搞一個servlet+jsp+el表達式+jstl+mysql+mvc的綜合性小項目。
遇到了一個問題:Template中的query和queryForObject到底有什麼區別呢?因爲有時候用query,有時候用queryForObject,實在是玄乎。搜索大量的資料,並沒有我想要的答案。
我想知道:是不是 queryForObject(String sql, RowMapper<T> rowMapper, Object... args) 只返回一條記錄,而
query(String sql, RowMapper<T> rowMapper) 可以返回一組記錄?爲什麼有這個疑問呢?因爲我遇到過這種用法,如下圖:
這裏 query 查詢後直接把數據封裝成User對象並以 List<User> 的方式返回, 而 queryForObject 卻只返回了一個User對象。那麼是不是隻要是這種形式的的 query 和 queryForObject 就都會分別返回 List<User> 和 一個User對象 ?我不確定,但是網上又找不到我想要的答案。無奈之下,我開始了我的第一次深入理解源碼之旅。
二. 查看源碼 + 深度剖析
1.queryForObject
首先,我按ctrl+左鍵點擊 queryForObject 進入源碼
我們需要分析的是這個方法的源碼。(這裏聲明一下,返回值其實已經可以解決我的問題了,但是爲了學會剖析源碼的方法,就當我們不知道這個返回值。。。)
可以看到他用 List<T> results 來存儲了查詢的結果,但是並不是直接返回了,從他拋出異常和她返回的方法可以看出,是爲了保證數據的安全性才這麼做的,如果返回數據不符合規定就拋出異常,而不是直接返回被輕易取出不符合規定的數據。再往下看 return 語句,這個方法一般人應該不知道是啥,沒關係,繼續看他的源碼。
首先他用size存儲按 sql語句 從數據庫中返回的結果集 results,如果 結果集爲 null,size就爲0。否則 size 就爲結果集長度。
然後判斷 size :
1. ==0:拋出空結果集異常。
2. >1:拋出不正確的結果集長度異常
3. ==1:因爲返回結果集不可能爲負數,所以else判斷的肯定是size==1的情況。這時候返回結果集的迭代器的next(),即 讓迭代器的指針指向下一位。
(* 當創建完成指向某個集合或者容器的Iterator對象是,這是的指針其實指向的是第一個元素的上方,即指向一個空)
到這裏,我們就知道了一個既定事實,他返回的長度必定爲1,也就是說:queryForObject 只返回了一個User對象,如果長度不是1就會拋出異常。
回過頭來看上一層源碼,我們就可以輕易的明白他爲什麼要在return時先調用方法:
其實就是爲了
1. 保證返回的數據只有一條:比如這裏是查詢User對象的方法,那麼該方法就只會返回一個封裝好的User對象 。
2. 將迭代器的指針往下移一位 :方便用戶去取數據
2.query
這個比較簡單一點,我們可以很清楚的看到他返回一個List集合,並且return也是直接return了。
三. 結語
至此,查看源碼+深度剖析就完成了,同時也解決了我的疑惑。在這裏建議大家學會去看源碼,
有時候比上網去查資料還要快。
同時也能夠提升你的代碼閱讀能力和理解能力
還能夠讓你感受到代碼之美,讓你以後以更加優雅的方式去寫代碼!
不行了,實在編不下去了,蛤蛤蛤~
以後遇到有深度的問題還會記錄一些深度剖析源碼的例子!
我是一個小coder,希望和努力的大家一起前行,加油 ~