情景一
基本标签(insert,update ,select)及属性(parameterClass,resultClass) -
5 -
情景二
子标签(<sql /><include
/>)及转义处理 - 7 -
情景三
高阶标签(<dynamic />)及属性(resultMap) - 8
-
情景四
储存过程标<procedure/>及属性parameterMap - 10
-
参与人员:
发布记录
版本 |
日期 |
作者 |
说明 |
0.0 |
2009-08-21 |
毛凌志 |
初稿 |
以SQL Mapping为核心,提供基于ado.net之上的一层简单抽象,将数据库中数据映射到领域模型的持久层框架
更详细的使用过程,可参见视频。
优点 |
缺点 |
|
|
情景一 基本标签(insert,update ,select)及属性(parameterClass,resultClass)
在iBatis.net原理一节示例了使用ibatis.net进行insert和select操作,下面展示介绍如何具体的进行SqlMapping。
在SqlMapping的配置文件本例中为Account.xml文件中,添加如下的标签段
并将此Account.xml文件的路径加入到sqlmap.config中
在iBatis.net中提供了五种常用的标签如下表示
表1
基本SQL Mapping标签
标签 |
说明 |
<insert></insert> |
删除sql语句 |
<update></update> |
更新sql语句 |
<select></select> |
选取sql语句 |
<delete></delete> |
删除sql语句 |
<procedure></procedure> |
调用储存过程 |
在这些容器标签中有一些常用的属性如下所示
属性 |
说明 |
Id |
用于唯一标识一条sql语句 |
resultClass |
用于将sql语句返回的字段和resultClass提定的类进行隐式的自动映射 |
parameterClass |
用于指定输入参数的类型,如果输入参数有多个应使用Hashtable或是类进行包装 |
下面是关于这两条SQL语句的调用方法和测试
情景二 子标签(<sql /><include />)及转义处理
在一些复杂的情景中,为了简化SQL的编写工作,ibatis.net提供了一些标签用于简化SQL的编写操作。可以将可复用的sql语句写在<sql></sql>标签中,然后中<select/><insert/><update/><delete/>等标签中使用<include
refid="xxx" />进行引用,其中refid属性指向<sql/>子标签的标识id。
如下例中所示
在此例中,我们还使用了了<![CDATA[]]>,主要是在sql语句中有些特殊的字符如<>等,在xml中不能直接使用,因为我们将包含特殊字符的
SQL语句放入XML的CDATA块中
在此例中,通过Hashtable传入了两个参数,下面介绍了程序中是如何调用上面这段代码的
情景三 高阶标签(<dynamic />)及属性(resultMap)
当在进行一些组合查询等需要灵活组装sql的情景时,需要用到dynamic标签。如下所示。
这段代码可以大至翻译为如下的伪代码
Account acc=new Account();
acc.Item="买菜";
if(acc.Item!=null)
sql+="where item like '%"+acc.Item+"%'";
If(acc.Money!=null)
sql+="or Money like '%20%';
this.Response.Write(sql)
表3 <dynamic>元素
名称 |
描述 |
isEqual |
如果参数相等于值则查询条件有效 |
isNotEqual |
如果参数不等于值则查询条件有效 |
isGreaterThan |
如果参数大于值则查询条件有效 |
isGreaterEqual |
如果参数大于等于值则查询条件有效 |
isLessEqual |
如果参数小于值则查询条件有效 |
isPropertyAvaiable |
如果参数可用则查询条件有效 |
isNotPropertyAvaiable |
如果参数不可用则查询条件有效 |
isNull |
如果参数为Null则查询条件有效 |
isNotNull |
如果参数不为Null则查询条件有效 |
isEmpty |
如果参数为空则查询条件有效 |
isNotEmpty |
如果参数不为空则查询条件有效。参数的数据类型为Collection、string时参数不为 |
isParameterPresent |
如果参数类为Null则查询条件有效 |
isNotParameterPresent |
如果参数类不为Null则查询条件有效 |
在上面的属性中使用了resultMap属性,原先使用resultClass是自动隐式的将sql语句映射出的字段。而resultMap属性用于将select输出的语句进行显示的映射,
如下所示
将sql语句取出数据的字段名名称和领域模型进行一个显示的映射。
情景四 储存过程标<procedure/>及属性parameterMap
在SQL Mapping中专门为储存过程提供了标签,如下所示:
其调用方法是在容器标签中撰写储存过程的名称,此写法适合SQL Server,针对其它数据库的方法参见
注意到在这里我们使用了一个新的属性parameterMap,它的作用是对输入的参数进行显示的映射,之前在情景一中介绍过parameterClass,它和parameterMap类似均是用来对传入sql的参数时行映射,不同的是对parameterClass是隐式映射的,而parameterMap是显示的映射。
注意到,有一个direction属性默认为储存过程的in,可以特别指定用于其它的方式如out或inout等。
在这里我们也使用了resultMap属性,该属性已在情景三中进行了介绍,读者忘了可以再温习一下
关于储存过程的具体的调用方法参见如下的示例,该储存过程的作用是对Accounts表进行分页返回指定页面的记录数和总的记录数。
当我们执行SQL语句取出需要的数据库,也做了SQL
Mapping的映射,最终我们的目的是希望将取出的数据以我们需要的形式(或者说是数据结构)呈现给我们。那么ISqlMapper接口就是来实现这一操作的,如下图所示。
方法 |
说明 |
QueryForObject<T>(string,object) |
Overloaded. Executes a Sql |
QueryForList<T>(string,object) |
Overloaded. Executes a Sql |
QueryForDictionary<K,V>(string,object,string,string) |
Overloaded. Executes the |
Insert(string,object) |
Executes a Sql INSERT |
Update(string,object) |
Executes a Sql UPDATE |
Delete(string,object) |
Executes a Sql DELETE |
参见情景二
在数据库插入一条数据的时候,经常是需要返回插入这条数据的主键。但是数据库供应商之间生成主键的方式都不一样。
有些是预先生成(pre-generate)主键的,如Oracle和PostgreSQL;有些是事后生成(post-generate)主键的,如MySQL和SQL
Server。但是不管是哪种方式,我们都可以用iBATIS的节点来获取语句所产生的主键。
Oracle
<insert id="insertProduct-ORACLE"
parameterClass="product">
<selectKey resultClass="int" type="pre"
keyProperty="id" >
SELECT STOCKIDSEQUENCE.NEXTVAL AS VALUE FROM
DUAL
selectKey>
insert into PRODUCT (PRD_ID,PRD_DESCRIPTION)
values (#id#,#description#)
insert>
SqlServer
<insert id="insertProduct-MS-SQL"
parameterClass="product">
insert into PRODUCT (PRD_DESCRIPTION)
values (#description#)
<selectKey resultClass="int" type="post"
keyProperty="id" >
select @@IDENTITY as value
</selectKey>
</insert>
MySQL
<insert id="insertProduct-MYSQL"
parameterClass="product">
insert into PRODUCT (PRD_DESCRIPTION)
values (#description#)
<selectKey resultClass="int" type="post"
keyProperty="id" >
select LAST_INSERT_ID() as value
</selectKey>
</insert>
SQLite
<insert id="Create"
parameterClass="Subject">
INSERT INTO SUBJECT
(SubjectName,QuestionCount,IsNowPaper)
VALUES(#SubjectName#,#QuestionCount#,#IsNowPaper#)
<selectKey resultClass="int" type="post"
property="SubjectId">
SELECT seq
FROM sqlite_sequence
WHERE (name = 'SUBJECT')
</selectKey>
</insert>
SqlServer
<parameterMap id="pm_ErickPagination"
class="System.Collections.Hashtable">
<parameter property="PageSize"/>
<parameter property="CurrentPage"/>
<parameter property="TotalCount" column="TotalCount"
direction="Output" />
</parameterMap>
<procedure id="sp_ErickPagination"
parameterMap="pm_ErickPagination"
resultMap="FindAllResult">
ErickPagination
</procedure>
Oracle
<parameterMap id="userParam" class="user">
<parameter property="username"/>
<parameter property="email"/>
</parameterMap>
<procedure id="sendEmail" parameterMap="userParam">
{call sendMail(?,?)}
</procedure>