看看 iBATIS SQL Maps 是怎樣從數據庫按照 one-to-many 關係查詢數據的:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> <sqlMap> <resultMap id="get-autoInfo-result" class="bo.AutoInfo"> <result property="id" column="auto_id"/> <result property="licensePlate" column="license_plate"/> </resultMap> <resultMap id="get-people-result" class="bo.People"> <result property="id" column="owner_id"/> <result property="name" column="name"/> <result property="address" column="address"/> <result property="autoInfoList" column="owner_id" select="getAutoInfo"/> </resultMap> <select id="getPeople" resultMap="get-people-result" parameterClass="bo.People"> <![CDATA[ select * from people where owner_id=#id# ]]> </select> <select id="getAutoInfo" resultMap="get-autoInfo-result" parameterClass="int"> <![CDATA[ select * from auto_info where owner_no=#id# ]]> </select> </sqlMap> |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> <sqlMap> <resultMap id="get-autoInfo-result" class="bo.AutoInfo"> <result property="id" column="auto_id"/> <result property="licensePlate" column="license_plate"/> </resultMap> <resultMap id="get-people-result" class="bo.People"> <result property="id" column="owner_id"/> <result property="name" column="name"/> <result property="address" column="address"/> <result property="autoInfoList" column="owner_id" select="getAutoInfo"/> </resultMap> <select id="getPeople" resultMap="get-people-result" parameterClass="bo.People"> <![CDATA[ select * from people where owner_id=#id# ]]> </select> <select id="getAutoInfo" resultMap="get-autoInfo-result" parameterClass="int"> <![CDATA[ select * from auto_info where owner_no=#id# ]]> </select> </sqlMap> |
resultMap id="get-autoInfo-result" class="bo.AutoInfo"
resultMap 是 iBATIS SQL Maps 框架中重要組件之一,你也許還記得 resultClass 吧?兩者概念基本一致。resultMap 則是可定製 Mapped Statement 返回對象的。可定製表現在:比如我有一張數據表包含10個字段,但我的 POJO 只定義了5個屬性,這時,只要取出我關心的字段就行。和 Hibernate 類似,resultMap 的 result 元素定義了 POJO 屬性到數據表字段的映射。
需要說明的是 result 元素 select 屬性,該屬性類似於加載了一個子查詢,並自動載入,如果這個子查詢包含多條結果,就自動把結果裝載進 List 類型。該 result 元素對應 People 中的屬性爲”autoInfoList”,而由 Hibernate 生成的 People 卻是 Set 類型”autoInfoSet”,這兩種類型無法直接互轉,所以我修改了 POJO 屬性。
select id="getPeople" resultMap="get-people-result" parameterClass="bo.People"
此爲 select 類型 Mapped Statement。傳入 People 實例,返回爲自己定製、包含”autoInfoList”的 People 實例。傳入People 類型參數是爲了便於多字段匹配查詢,今天也許我只需利用 People.id 單字段匹配就能得到結果,但下次的新需求也許是 People.address 和 People.name 聯合匹配!
相應程序代碼:
package test; import java.io.Reader; import java.util.List; import com.ibatis.sqlmap.client.*; import com.ibatis.common.resources.*; import bo.*; public class AutoMag { private Reader reader; private People people=new People(); private SqlMapClient sqlMap; private String resource = "SqlMapConfig.xml"; public People findPeople() throws Exception{ reader = Resources.getResourceAsReader(resource); sqlMap=SqlMapClientBuilder.buildSqlMapClient(reader); people.setId(new Integer("1")); people=(People)sqlMap.queryForObject("getPeople",people); return people; } } |
package test; import java.io.Reader; import java.util.List; import com.ibatis.sqlmap.client.*; import com.ibatis.common.resources.*; import bo.*; public class AutoMag { private Reader reader; private People people=new People(); private SqlMapClient sqlMap; private String resource = "SqlMapConfig.xml"; public People findPeople() throws Exception{ reader = Resources.getResourceAsReader(resource); sqlMap=SqlMapClientBuilder.buildSqlMapClient(reader); people.setId(new Integer("1")); people=(People)sqlMap.queryForObject("getPeople",people); return people; } } |
sqlMap.queryForObject(String arg0, Object arg1)
此方法類似 Hibernate 的 session.load(…),傳入 Mapped Statement id,再傳入包含主鍵的對象實例。除我上面列舉的 sqlMap.queryForObject(String arg0, Object arg1) 外,還有重載方法:
people=(People)sqlMap.queryForObject("getPeople",people); 替換成 sqlMap.queryForObject("getPeople", people, people); |
people=(People)sqlMap.queryForObject("getPeople",people); 替換成 sqlMap.queryForObject("getPeople", people, people); |
第一個”people”是傳入參數,第二個”people”是返回的結果。要表達的意思一樣,只不過換了種表現形式。
下面我會講到如何以集合類持有多個 People 對象實例。
在車輛管理應用中,需要把人員一一列出,選中某個再顯示詳細內容。類似於這樣的需求,iBATIS SQL Maps 引入 sqlMap.queryForList(String arg0, Object arg1) 來滿足。
還記得我們的映射文件怎麼寫的?對了,傳入主鍵值再查詢!
但是,新需求不要任何條件,直接列出人員啊!難道還要再添加新的 Mapped Statement 來滿足?動態 Mapped Statement 能滿足在不改變映射文件的前提下提供有參數和無差數查詢:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> <sqlMap> <resultMap id="get-autoInfo-result" class="bo.AutoInfo"> <result property="id" column="auto_id"/> <result property="licensePlate" column="license_plate"/> </resultMap> <resultMap id="get-people-result" class="bo.People"> <result property="id" column="owner_id"/> <result property="name" column="name"/> <result property="address" column="address"/> <result property="autoInfoList" column="owner_id" select="getAutoInfo"/> </resultMap> <select id="getPeople" resultMap="get-people-result" parameterClass="bo.People"> <![CDATA[ select * from people ]]> <dynamic prepend="where"> <isNotNull property="id"> <![CDATA[ owner_id=#id# ]]> </isNotNull> </dynamic> </select> <select id="getAutoInfo" resultMap="get-autoInfo-result" parameterClass="int" resultClass="bo.AutoInfo"> <![CDATA[ select * from auto_info where owner_no=#id# ]]> </select> </sqlMap> |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" "http://www.ibatis.com/dtd/sql-map-2.dtd"> <sqlMap> <resultMap id="get-autoInfo-result" class="bo.AutoInfo"> <result property="id" column="auto_id"/> <result property="licensePlate" column="license_plate"/> </resultMap> <resultMap id="get-people-result" class="bo.People"> <result property="id" column="owner_id"/> <result property="name" column="name"/> <result property="address" column="address"/> <result property="autoInfoList" column="owner_id" select="getAutoInfo"/> </resultMap> <select id="getPeople" resultMap="get-people-result" parameterClass="bo.People"> <![CDATA[ select * from people ]]> <dynamic prepend="where"> <isNotNull property="id"> <![CDATA[ owner_id=#id# ]]> </isNotNull> </dynamic> </select> <select id="getAutoInfo" resultMap="get-autoInfo-result" parameterClass="int" resultClass="bo.AutoInfo"> <![CDATA[ select * from auto_info where owner_no=#id# ]]> </select> </sqlMap> |
dynamic prepend="where"
select 類型 Mapped Statement 的本質並無改變,只是通過 dynamic 元素定義了動態 where 子句。dynamic 元素屬性 prepend=”where”在一元判定元素 isNotNull 返回”true”時有效。isNotNull 元素屬性 property="id" 用於判定 People.id 是否爲 null,假如未傳入包含主鍵值的 People 實例,dynamic 元素將會無效,反之則亦然,這樣就達到了在不改變映射文件的前提下實現動態 SQL 的目的。關於一元判定元素和二元判定元素的詳細資料請查閱官方文檔,如能恰當利用這些判定元素,動態 SQL 將會更靈活。
相應程序代碼:
package test; import java.io.Reader; import java.util.List; import com.ibatis.sqlmap.client.*; import com.ibatis.common.resources.*; import bo.*; public class AutoMag { private Reader reader; private People people=new People(); private SqlMapClient sqlMap; private String resource = "SqlMapConfig.xml"; public List findPeople() throws Exception{ reader = Resources.getResourceAsReader(resource); sqlMap=SqlMapClientBuilder.buildSqlMapClient(reader); List list=sqlMap.queryForList("getPeople",null); return list; } } |
package test; import java.io.Reader; import java.util.List; import com.ibatis.sqlmap.client.*; import com.ibatis.common.resources.*; import bo.*; public class AutoMag { private Reader reader; private People people=new People(); private SqlMapClient sqlMap; private String resource = "SqlMapConfig.xml"; public List findPeople() throws Exception{ reader = Resources.getResourceAsReader(resource); sqlMap=SqlMapClientBuilder.buildSqlMapClient(reader); List list=sqlMap.queryForList("getPeople",null); return list; } } |
傳入 Mapped Statement id,再傳入未包含主鍵的對象實例,也可以乾脆傳 null 進去。重載方法 sqlMap.queryForList(String arg0, Object arg1, int arg2, int arg3
) 用於分頁,arg2、arg3分別代表頁碼和每頁個數。
好了,使用動態 Mapped Statement,再試試 queryForObject(String arg0, Object arg1) 吧!
(請注意!引用、轉貼本文應註明原作者:Rosen Jiang 以及出處:http://blog.csdn.net/rosen)
(請注意!引用、轉貼本文應註明原作者:Rosen Jiang 以及出處:http://blog.csdn.net/rosen)