先說點基礎的內容,iBatis並不是真正意義上的ORM,官方文檔中稱其爲dataMapper,是數據映射器,也就是一種映射查詢工具。iBatis不是萬能的,在某些它不能處理的問題時,不能放棄使用JDBC API,那纔是根本中的根本。
在iBatis中,建議使用JavaBean,因爲我們是面向對象的設計,那麼在系統設計時肯定創建了很多刻畫具體對象的類,使用JavaBean就可以直接操作getter方法來獲取內容。就像是Hibernate中的PO一樣。下面來說一種如何獲取Bean中屬性名稱和屬性類型的方法,這在開發時可能會用到。
先定義一個JavaBean,刻畫用戶模型嗎,如下:
- package ibatis.model;
- public class User implements java.io.Serializable {
- private Integer userId;
- private String userName;
- private String password;
- private String mobile;
- private String email;
- public User() {
- super();
- }
- public User(Integer userId, String userName, String password,
- String mobile, String email) {
- super();
- this.userId = userId;
- this.userName = userName;
- this.password = password;
- this.mobile = mobile;
- this.email = email;
- }
- // 省略getter和setter方法
- @Override
- public String toString() {
- return "User [email=" + email + ", mobile=" + mobile + ", password="
- + password + ", userId=" + userId + ", userName=" + userName
- + "]";
- }
- }
寫一個方法來測試,如下:
- public static void main(String[] args) {
- try {
- PropertyDescriptor[] pd = Introspector.getBeanInfo(User.class).getPropertyDescriptors();
- for (int i = 0; i < pd.length; i++) {
- System.out.println(pd[i].getName() + " ("
- + pd[i].getPropertyType().getName() + ")");
- }
- } catch (IntrospectionException e) {
- e.printStackTrace();
- }
- }
在控制檯,我們獲得如下輸出:
- class (java.lang.Class)
- email (java.lang.String)
- mobile (java.lang.String)
- password (java.lang.String)
- userId (java.lang.Integer)
- userName (java.lang.String)
在定位BUG時,這是很好的一種手段。
接下來,我們來說一下三個常用的查詢方法,它們的命名和Spring的JdbcTemplate/SqlMapClientTemplate很像,但是要區分開。
首先是queryForObject()方法,它返回數據庫查詢的一條結果,並放入到Java對象中,這裏的一條記錄可以是一個JavaBean,也可以是Java的集合類型。它可以根據<select>標籤中配置的resultClass屬性來確定的,如果不指定resultClass屬性,那麼查詢結果就是null了,因爲iBatis不知道怎麼處理這個結果,而且我們也沒有配置結果映射(resultMap)。
首先我們根據上面的User類型,將resultClass設置爲User,代碼如下:
- <sqlMap namespace="User">
- <typeAlias alias="User" type="ibatis.model.User" />
- <select id="getUserByName" parameterClass="java.lang.String"
- resultClass="User">
- select *
- from users
- where USERNAME=#VARCHAR#
- </select>
- </sqlMap>
這時要求User類中必須要有一個默認的構造方法,否則將不能實例化這個對象,拋出異常,這一點不能忘記(如果重載了構造方法的話)。我們寫一個程序:
- System.out
- .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類中的默認構造方法)
- User user=new User(null, null, null, null, null);
- user = (User) sqlMap.queryForObject("User.getUserByName", "sarin",
- user);
- 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了):
- Map map = sqlMap.queryForMap("User.getAllUsers", null,"userId");
- System.out.println(map);
正如你所想,這段代碼的輸出爲:
- {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,是鍵,那麼它們是什麼類型的呢?我們使用如下代碼來看看:
- System.out.println(map.keySet().iterator().next().getClass());
得到結果:class java.lang.Integer,說明這是字段相對應的,因爲這裏我們沒有將查詢結果和JavaBean相關聯。那麼HashMap中存儲的value是什麼類型呢?我們來看,代碼如下:
- System.out.println(map.get(1).getClass());
打印得到:class java.util.HashMap,說明存儲的還是HashMap。而queryForMap()的第二個重載方法則是指定了value的內容,我們來看:
- Map map = sqlMap.queryForMap("User.getAllUsers", null, "userId",
- "mobile");
- System.out.println(map);
這將打印:{1=15940912345, 2=15940912345},這回就清楚了吧,而且得到的mobile的類型是String,也就容易理解了。記住一點,queryForMap()方法返回的可以是一條也可以是多條記錄。但是在實踐中往往用它來獲取一條完整的記錄,那麼使用Map的get()方法就能獲取到其中的值了,非常方便。
下面來看queryForList()方法,同樣,該方法的方法簽名也有兩類形式:第一類是queryForList(String id, Object parameter) throws SQLException,或者不需要參數,這很好理解了。看個例子:(SqlMap中的resultClass設置爲hashmap)
- List users = sqlMap.queryForList("User.getAllUsers");
- System.out.println(users);
打印的結果是:
- [{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,那麼得到:
- [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),以此類推。
一家之言,僅供參考。歡迎交流。