在企業級應用開發中,複雜的組合查詢是常見需求。使用者可能根據多種條件任意組合查詢,例如:僅輸入姓名、僅輸入地址、兩者皆輸入、或皆不輸入。傳統做法需撰寫大量 if-else 判斷,為每種組合定義獨立的 SQL 陳述式,不僅程式碼冗餘,維護成本極高。iBATIS 引入動態映射機制,允許在單一 Statement 定義中根據參數動態生成 SQL,徹底解決此痛點。
假設有一個使用者查詢頁面,包含「姓名」與「地址」兩個輸入欄位。根據使用者輸入,系統需生成不同的 WHERE 子句:
SELECT * FROM t_userSELECT * FROM t_user WHERE name LIKE '%Erica%'SELECT * FROM t_user WHERE address LIKE '%Beijing%'SELECT * FROM t_user WHERE name LIKE '%Erica%' AND address LIKE '%Beijing%'在 SQL Map XML 中使用 <dynamic> 標籤包裹 WHERE 子句,搭配 <isNotEmpty> 判斷屬性是否為空:
<select id="getUsers" resultClass="User">
SELECT id, name, sex
FROM t_user
<dynamic prepend="WHERE">
<isNotEmpty property="name" prepend="AND">
name LIKE #name#
</isNotEmpty>
<isNotEmpty property="address" prepend="AND">
address LIKE #address#
</isNotEmpty>
</dynamic>
</select>
關鍵屬性說明:
prepend="WHERE":動態節點內容若非空,自動加上 WHERE 關鍵字。prepend="AND":判斷節點內容若非空,自動加上 AND 連接詞。iBATIS 會智慧判斷首個條件是否需要 AND,自動省略。property:對應參數物件的屬性名(如 user.getName())。| 節點名 | 描述 |
|---|---|
isNull | 屬性值為 null |
isNotNull | 屬性值不為 null |
isEmpty | 屬性為空字串或集合大小為 0 |
isNotEmpty | 屬性非空字串且集合大小 > 0 |
isProperty | 參數類中是否提供了此屬性 |
isNotProperty | 與 isProperty 相反 |
| 節點名 | 關係 |
|---|---|
isEqual | 相等 |
isNotEqual | 不等 |
isGreaterThan | 大於 |
isGreaterEqual | 大於等於 |
isLessThan | 小於 |
isLessEqual | 小於等於 |
二元判斷需指定 property 與 compareValue 屬性,例如:<isGreaterThan property="age" compareValue="18">age = #age#</isGreaterThan>。
動態映射支援巢狀判斷,實現更複雜的業務邏輯。例如:僅當使用者提供姓名時,才允許結合地址查詢:
<isNotEmpty property="name">
name = #name#
<isNotEmpty property="address" prepend="AND">
address = #address#
</isNotEmpty>
</isNotEmpty>
此結構確保「地址條件」只有在「姓名條件」存在時才會被加入 SQL。
User user = new User();
user.setName(request.getParameter("name"));
user.setAddress(request.getParameter("address"));
List users = sqlMap.queryForList("User.getUsers", user);
iBATIS 會根據配置規則,在運行期動態生成對應的 PreparedStatement 並填充參數。
iBATIS 動態映射透過 dynamic、判斷節點與 prepend 屬性的協作,將複雜的條件組合邏輯內建於 SQL 定義中,極大簡化了資料存取層程式碼,提升了系統的可維護性與擴展性。掌握其核心機制,是高效開發企業級查詢功能的關鍵。