看看 iBATIS SQL Maps 是怎樣從數據庫按照 one-to-many 關系查詢數據的:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
<sqlMap>
??? <resultMap id="get-people-result" class="bo.People">
? <select id="getPeople" resultMap="get-people-result" parameterClass="bo.People">
? <select id="getAutoInfo" resultMap="get-autoInfo-result" parameterClass="int">
?
??? PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
??? "
http://www.ibatis.com/dtd/sql-map-2.dtd
">
??? <resultMap id="get-autoInfo-result" class="bo.AutoInfo">
??????? <result property="id" column="auto_id"/>
??????? <result property="licensePlate" column="license_plate"/>
??? </resultMap>
??????? <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>
?????? <![CDATA[
?????? select * from people where owner_id=#id#
??????? ]]>
? </select>
?????? <![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 com.ibatis.sqlmap.client.*;
import bo.*;
public class AutoMag {
?private Reader reader;
??
import java.util.List;
import com.ibatis.common.resources.*;
?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 ” 是返回的結果。 要表達的意思一樣,只不過換了種表現形式 。
下面我會講到如何以集合類持有多個 People 對象實例。
在車輛管理應用中,需要把人員一一列出,選中某個再顯示詳細內容。類似于這樣的需求,
iBATIS SQL Maps
引入
sqlMap.queryForList(String arg0, Object arg1)
來滿足。
??????
還記得我們的映射文件怎么寫的?對了,傳入主鍵值再查詢!
但是,新需求不要任何條件,直接列出人員啊!難道還要再添加新的 Mapped Statement 來滿足?動態 Mapped Statement 能滿足在不改變映射文件的前提下提供有參數和無差數查詢:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
<sqlMap>
??? <resultMap id="get-people-result" class="bo.People">
? <select id="getPeople" resultMap="get-people-result" parameterClass="bo.People">
? <select id="getAutoInfo" resultMap="get-autoInfo-result" parameterClass="int"
?
??? PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
??? "
http://www.ibatis.com/dtd/sql-map-2.dtd
">
??? <resultMap id="get-autoInfo-result" class="bo.AutoInfo">
??????? <result property="id" column="auto_id"/>
??????? <result property="licensePlate" column="license_plate"/>
??? </resultMap>
??????? <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>
?????? <![CDATA[
?????? select * from people
?????? ]]>
?????? <dynamic prepend="where">
???????? <isNotNull property="id">
?????????? <![CDATA[
?????????? owner_id=#id#
?????????? ]]>
???????? </isNotNull>
?????? </dynamic>
? </select>
??????????????????? 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 com.ibatis.sqlmap.client.*;
import bo.*;
public class AutoMag {
?private Reader reader;
?
import java.util.List;
import com.ibatis.common.resources.*;
?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://www.aygfsteel.com/rosen