ibatis介紹
使用ibatis 提供的ORM機制,對業務邏輯實現人員而言,面對的是純粹的java對象, 這一層與通過Hibernate 實現ORM 而言基本一致,而對于具體的數據操作,Hibernate 會自動生成SQL 語句,而ibatis 則要求開發者編寫具體的SQL 語句。相對Hibernate等 “全自動”ORM機制而言,ibatis 以SQL開發的工作量和數據庫移植性上的讓步,為系統 設計提供了更大的自由空間。作為“全自動”ORM 實現的一種有益補充,ibatis 的出現顯 得別具意義。
版權聲明:任何獲得Matrix授權的網站,轉載時請務必保留以下作者信息和鏈接
作者:fellow99
原文:http://www.matrix.org.cn/resource/article/44/44410_iBatis.Html
要害字:iBatis;ORM
一、為什么要設計“通用”的東西
在大多數時候,我們所需要的持久層對象(PO)大多都是一張表(or視圖)對應一個類。按照Hibernate的思想,就是拋開數據庫的束縛,把焦點集中到業務對象中。而很多自動化工具的確讓做到了通過表結構生成對應的對象,or通過對象自動生成表。對于小項目來說,一切都是簡單的;對于有規范設計的項目來說,PO的設計也不是一件困難的工作。但是對于那些業務變動頻繁的項目來說,改動PO可能成了一件很繁重的工作。試想一下,假設某個表需要增加一個字段:對于Hibernate(or iBaits),首先要改配置文件,然后PO,然后DAO(也許沒有),然后業務邏輯,然后JO,然后界面,etc,貫通了全部層次。
恩,寫程序的都不喜歡這些重復勞動,但是做企業級應用的誰不是天天在這些工作中打滾。
研究過iBaits以后,發現有些通用的方法可以解決,就是設計一個通用的持久層對象。
二、基于什么技術
iBatis可以使用Map對象作為PO,Hibernate似乎也有相關的功能(我沒有細看,不確定)。
iBatis執行一條指令的過程大概是這樣的:
其中圈圈1、2、3描述了iBatis最重要的三個對象。
圈圈1:statement簡單來說就是存儲sql語句的配置信息,一個最簡單的statement:
insert into PRODUCT (PRD_ID, PRD_DESCRipTION) values (1, “Shih Tzu”)
insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);
insert into PRODUCT values (#id#, #description#, #price#)
insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)
values (#id:NUMERIC:-999999#, #description:VARCHAR:NO_ENTRY#);
insert into PRODUCT values (#id#, #description#, #price#, #classify.id#)
select * from PRODUCT order by $preferredOrder$
select * from PRODUCT
SELECT PER_ID as id, PER_FIRST_NAME as firstName
FROM PERSON WHERE PER_ID = #value#
public class CustomPO {
protected String moduleTable; //該PO對應的表名(視圖名)
protected int id; //表的id
protected int parentID; //父表的id(假如有的話)
protected Map fieldMap; //字段Map,核心,用于存儲字段及其值
public String getModuleTable()
public void setModuleTable(String moduleTable)
public int getId()
public void setId(int id)
public int getParentID()
public void setParentID(int parentID)
public Map getFieldMap()
public void setFieldMap(Map fieldMap)
public void copyFieldMap(Map fieldMap)
//取得字段名列表
public List getFieldList()
//設置字段名列表。假如fieldMap沒有相應的字段,則增加,字段值為null;假如有則不增加。
public void setFieldList(List fieldList)
//返回字段的“字段名 - 字段值”列表,使用com.fellow.pub.util.KeyValuePair對象作為存儲
public List getFieldValueList()
}
通過id查找
特點:iterate這個fieldList列表,生成要輸出的字段
-->
插入一條新紀錄
特點:iterate這個fieldValueList列表,分別取得其元素的key和value值
注重$號和#號的使用方法,還有最后怎么取得insert后的id值(各種數據庫都可能不同)
-->
INSERT INTO $moduleTable$ (parentID
$fieldValueList[].key$
)
VALUES (#parentID#
#fieldValueList[].value#
)
SELECT last_insert_id()
更新一條紀錄
特點:iterate這個fieldValueList列表,分別取得其元素的key和value值
注重$號和#號的使用方法
-->
UPDATE $moduleTable$ SET
$fieldValueList[].key$ = #fieldValueList[].value#
WHERE id = #id#
DELETE FROM $moduleTable$ WHERE id = #id#
public interface ICustomDAO {
/**
* 通過傳入moduleTable和id取得一條記錄
*/
CustomPO findByID(String moduleTable, int id) throws Exception;
/**
* 通過傳入CustomPO對象取得一條記錄
* @param po CustomPO 該對象在傳入前應該先設置moduleTable和id參數,
* 并且使用setFieldList()函數設置字段列表(該設置決定所返回的字段)。
*/
CustomPO findByID(CustomPO po) throws Exception;
/**
* 通過傳入moduleTable和parentID取得一條記錄
*/
CustomPO findByParentID(String moduleTable, int parentID) throws Exception;
/**
* 通過傳入CustomPO對象插入一條記錄
* @param po CustomPO 該對象在傳入前應該先設置moduleTable和id參數,
* 并且使用setFieldMap()函數設置“字段-值”對。
*/
void insert(CustomPO po) throws Exception;
/**
* 通過傳入CustomPO對象更新一條記錄
* @param po CustomPO 該對象在傳入前應該先設置moduleTable和id參數,
* 并且使用setFieldMap()函數設置“字段-值”對。
*/
void update(CustomPO po) throws Exception;
/**
* 刪除moduleTable和id所對應的記錄
*/
void delete(String moduleTable, int id) throws Exception;
}
protected void fill(Map result, CustomPO po) {
Long returnId = (Long) result.get("id");
Long returnParentID = (Long) result.get("parentID");
result.remove("id");
result.remove("parentID");
if (returnId != null) po.setId(returnId.intValue());
if (returnParentID != null) po.setParentID(returnParentID.intValue());
po.setFieldMap(result);
}
//查詢
Map result = (Map)this.queryForObject("customPO_findByID", po);
//處理返回結果
if(result == null)
po = null;
else
fill(result, po);
//增刪改
this.insert("customPO_insert", po);
this.update("customPO_update", po);
this.delete("customPO_delete", po);
。。。
新聞熱點
疑難解答