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);
。。。
新闻热点
疑难解答