ibatis queryForObject() 、queryForList()、queryForMap()

先說點基礎的內容,iBatis並不是真正意義上的ORM,官方文檔中稱其爲dataMapper,是數據映射器,也就是一種映射查詢工具。iBatis不是萬能的,在某些它不能處理的問題時,不能放棄使用JDBC API,那纔是根本中的根本。
    在iBatis中,建議使用JavaBean,因爲我們是面向對象的設計,那麼在系統設計時肯定創建了很多刻畫具體對象的類,使用JavaBean就可以直接操作getter方法來獲取內容。就像是Hibernate中的PO一樣。下面來說一種如何獲取Bean中屬性名稱和屬性類型的方法,這在開發時可能會用到。
    先定義一個JavaBean,刻畫用戶模型嗎,如下:

Java代碼  收藏代碼
  1. package ibatis.model;  
  2. public class User implements java.io.Serializable {  
  3.     private Integer userId;  
  4.     private String userName;  
  5.     private String password;  
  6.     private String mobile;  
  7.     private String email;  
  8.     public User() {  
  9.         super();  
  10.     }  
  11.     public User(Integer userId, String userName, String password,  
  12.             String mobile, String email) {  
  13.         super();  
  14.         this.userId = userId;  
  15.         this.userName = userName;  
  16.         this.password = password;  
  17.         this.mobile = mobile;  
  18.         this.email = email;  
  19.     }  
  20. // 省略getter和setter方法  
  21.     @Override  
  22.     public String toString() {  
  23.         return "User [email=" + email + ", mobile=" + mobile + ", password="  
  24.                 + password + ", userId=" + userId + ", userName=" + userName  
  25.                 + "]";  
  26.     }  
  27. }  


    寫一個方法來測試,如下:

Java代碼  收藏代碼
  1. public static void main(String[] args) {  
  2.     try {  
  3.         PropertyDescriptor[] pd = Introspector.getBeanInfo(User.class).getPropertyDescriptors();  
  4.         for (int i = 0; i < pd.length; i++) {  
  5.             System.out.println(pd[i].getName() + " ("  
  6.                     + pd[i].getPropertyType().getName() + ")");  
  7.         }  
  8.     } catch (IntrospectionException e) {  
  9.         e.printStackTrace();  
  10.     }  
  11. }  


    在控制檯,我們獲得如下輸出:

Java代碼  收藏代碼
  1. class (java.lang.Class)  
  2. email (java.lang.String)  
  3. mobile (java.lang.String)  
  4. password (java.lang.String)  
  5. userId (java.lang.Integer)  
  6. userName (java.lang.String)  


    在定位BUG時,這是很好的一種手段。
    接下來,我們來說一下三個常用的查詢方法,它們的命名和Spring的JdbcTemplate/SqlMapClientTemplate很像,但是要區分開。
首先是queryForObject()方法,它返回數據庫查詢的一條結果,並放入到Java對象中,這裏的一條記錄可以是一個JavaBean,也可以是Java的集合類型。它可以根據<select>標籤中配置的resultClass屬性來確定的,如果不指定resultClass屬性,那麼查詢結果就是null了,因爲iBatis不知道怎麼處理這個結果,而且我們也沒有配置結果映射(resultMap)。
    首先我們根據上面的User類型,將resultClass設置爲User,代碼如下:

Xml代碼  收藏代碼
  1. <sqlMap namespace="User">  
  2.     <typeAlias alias="User" type="ibatis.model.User" />  
  3.     <select id="getUserByName" parameterClass="java.lang.String"  
  4.         resultClass="User">  
  5.         select *  
  6.         from users  
  7.         where USERNAME=#VARCHAR#  
  8.     </select>  
  9. </sqlMap>  


    這時要求User類中必須要有一個默認的構造方法,否則將不能實例化這個對象,拋出異常,這一點不能忘記(如果重載了構造方法的話)。我們寫一個程序:

Java代碼  收藏代碼
  1. System.out  
  2.         .println(sqlMap.queryForObject("User.getUserByName""sarin").getClass().getName());  


    此時,輸出內容爲:ibatis.model.User,這就很清楚的看到了,查詢的結果類型是由<select>中的resultClass來確定的。
    queryForObject()的另外一個重載方法是Object queryForObject(String id, Object parameter, Object resultObject) throws Exception,這種方法是爲對象不能輕易創建的情況使用的(如沒有默認的構造方法的對象),那麼使用前面那種格式就會拋出異常,就需要使用這種方法,看下面代碼:(這裏去掉User類中的默認構造方法)

Java代碼  收藏代碼
  1. User user=new User(nullnullnullnullnull);  
  2. user = (User) sqlMap.queryForObject("User.getUserByName""sarin",  
  3.                 user);  
  4. System.out.println(user);  


    這樣才能獲得user對象。
    第二個方法是queryForMap()方法,返回結果可以是一條,也可以是多條。它的方法簽名有兩種形式:第一種是Map queryForMap(String id, Object parameter, String key) throws SQLException,第二種是再多一個參數String value。前面兩個參數好理解,就是select標籤的id和傳入的參數,而後面的key和value是什麼意思呢?key指定了Map中存儲的鍵,而value確定了存儲的值,不設置value時則存儲查詢的一個對象,如下面代碼(此時已經將select的resultClass設置爲hashmap了):

Java代碼  收藏代碼
  1. Map map = sqlMap.queryForMap("User.getAllUsers"null,"userId");  
  2. System.out.println(map);  


    正如你所想,這段代碼的輸出爲:

Java代碼  收藏代碼
  1. {1={email=gmail@gmail.com, userId=1, userName=sarin, password=123, mobile=15940912345}, 2={email=gmail@gmail.com, userId=2, userName=sarin, password=123, mobile=15940912345}}  


    這裏的1和2就是key,是鍵,那麼它們是什麼類型的呢?我們使用如下代碼來看看:

Java代碼  收藏代碼
  1. System.out.println(map.keySet().iterator().next().getClass());  


    得到結果:class java.lang.Integer,說明這是字段相對應的,因爲這裏我們沒有將查詢結果和JavaBean相關聯。那麼HashMap中存儲的value是什麼類型呢?我們來看,代碼如下:

Java代碼  收藏代碼
  1. System.out.println(map.get(1).getClass());  


    打印得到:class java.util.HashMap,說明存儲的還是HashMap。而queryForMap()的第二個重載方法則是指定了value的內容,我們來看:

Java代碼  收藏代碼
  1. Map map = sqlMap.queryForMap("User.getAllUsers"null"userId",  
  2.         "mobile");  
  3. System.out.println(map);  


    這將打印:{1=15940912345, 2=15940912345},這回就清楚了吧,而且得到的mobile的類型是String,也就容易理解了。記住一點,queryForMap()方法返回的可以是一條也可以是多條記錄。但是在實踐中往往用它來獲取一條完整的記錄,那麼使用Map的get()方法就能獲取到其中的值了,非常方便。
    下面來看queryForList()方法,同樣,該方法的方法簽名也有兩類形式:第一類是queryForList(String id, Object parameter) throws SQLException,或者不需要參數,這很好理解了。看個例子:(SqlMap中的resultClass設置爲hashmap)

Java代碼  收藏代碼
  1. List users = sqlMap.queryForList("User.getAllUsers");  
  2. System.out.println(users);  


    打印的結果是:

Java代碼  收藏代碼
  1. [{email=gmail@gmail.com, userId=1, userName=sarin, password=123, mobile=15940912345}, {email=gmail@gmail.com, userId=2, userName=sarin, password=123, mobile=15940912345}]  


    就是List中裝入的是HashMap對象,在SqlMap中將hashmap換爲User,那麼得到:

Java代碼  收藏代碼
  1. [User [email=gmail@gmail.com, mobile=15940912345, password=123, userId=1, userName=nanlei], User [email=gmail@gmail.com, mobile=15940912345, password=123, userId=2, userName=sarin]]  


    queryForList()的第二類方法是queryForList(String id, Object parameter, int skip, int max) throws SQLException,可以看出後面多了兩個int類型的參數,那麼SQL中使用兩個int類型的參數能幹什麼?分頁,沒錯,這是主要應用。iBatis在queryForList()中提供了爲分頁提供支持的方法。記着skip是從0開始計算的,而max就是取出的條數,那麼取前10條就是(0,10),取11~20條就是(10,10),以此類推。
    一家之言,僅供參考。歡迎交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章