一、DomSqlMapBuilder
DomSqlMapBuilder,根据配置文件(sqlmap.config)生SqlMap实例。可通过Stream,Uri,FileInfo,XmlDocument来读取sqlmap.config配置信息。
二、SqlMap
SqlMap,是IBatisNet的核心组件,提供数据库操作的基本平台。SqlMap的实例,由DomSqlMapBuilder通过读取配置文件来创建。通常可用下面的方式将创建SqlMap实例的代码写在业务服务基类的构造函数中。
Assembly assembly = Assembly.Load("IBatisNetDemo");
Stream stream = assembly.GetManifestResourceStream("IBatisNetDemo.sqlmap.config");
DomSqlMapBuilder builder = new DomSqlMapBuilder();
SqlMap sqlMap = builder.Configure( stream );SqlMap是线程安全的,也就是说,在一个应用中,可以共享一个SqlMap实例。SqlMap提供了众多数据操作方法,下面是一些常用方法的示例,具体请参阅ibatisnet的官方开发手册 。
三、SqlMap基本操作
1.更新数据库操作(insert update delete),如,
SqlMap.BeginTransaction();
Person person = new Person();
Person.FirstName = “Zhang”;
Person.LastName = “shanyou”;
int Id = (int) SqlMap.Insert("InsertPerson", person);
SqlMap.CommitTransaction();
Int Id = 1;
Person person = SqlMap.QueryForObject<Person>("", Id);
return person;
Int Id = 1;
Person person = new Person();
person = SqlMap.QueryForObject<Person>("GetBirthday", Id, person);
return person;
IList<Person> list = null;
list = SqlMap.QueryForList<Person>("SelectAllPerson", null);
return list;
IList<Person> list = null;
list = SqlMap.QueryForList<Person>("SelectAllPerson", null, 0, 40);
return list;
public void RowHandler(object obj, IList list)
{
Product product = (Product) object;
product.Quantity = 10000;
}
SqlMapper.RowDelegate handler = new SqlMapper.RowDelegate(this.RowHandler);
IList list = sqlMap.QueryWithRowDelegate("getProductList", null, handler);
PaginatedList list = sqlMap.QueryForPaginatedList (“getProductList”, null, 10);
list.NextPage();
list.PreviousPage();
IDictionary map = sqlMap.QueryForMap (“getProductList”, null, “productCode”);
Product p = (Product) map[“EST-93”];
感觉相对于NHibernate来说,IBatisNet实体配置或者说映射文件而言。NHibernate的配置感觉更像是对象关系映射文件。例如,
<?xml version="1.0" encoding="utf-8" ?>2
<sqlMap namespace="Person" xmlns="http://ibatis.apache.org/mapping" 3
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >4
<!—模块配置-->5
<alias>6
<typeAlias alias="Person" type="IBatisNetDemo.Domain.Person,IBatisNetDemo" />7
</alias>8
<cacheModels>9
<cacheModel id="person-cache" implementation="MEMORY" >10
<flushInterval hours="24"/>11
<flushOnExecute statement="UpdateAccountViaInlineParameters"/>12
<flushOnExecute statement="UpdateAccountViaParameterMap"/>13
<property name="Type" value="Weak"/>14
</cacheModel>15
</cacheModels>16
<resultMaps>17
<resultMap id="SelectAllResult" class="Person">18
<result property="Id" column="PER_ID" />19
<result property="FirstName" column="PER_FIRST_NAME" />20
<result property="LastName" column="PER_LAST_NAME" />21
<result property="BirthDate" column="PER_BIRTH_DATE" />22
<result property="WeightInKilograms" column="PER_WEIGHT_KG" />23
<result property="HeightInMeters" column="PER_HEIGHT_M" />24
</resultMap>25
</resultMaps>26

27
<!—statement配置 à28
<statements>29
<select id="SelectAllPerson" resultMap="SelectAllResult" cacheModel="account-cache">30
select31
PER_ID,32
PER_FIRST_NAME,33
PER_LAST_NAME,34
PER_BIRTH_DATE,35
PER_WEIGHT_KG,36
PER_HEIGHT_M37
from PERSON 38
</select>39

40
<select id="SelectByPersonId" resultClass="Person" parameterClass="int">41
select42
PER_ID,43
PER_FIRST_NAME,44
PER_LAST_NAME,45
PER_BIRTH_DATE,46
PER_WEIGHT_KG,47
PER_HEIGHT_M48
from PERSON49
where PER_ID = #value#50
</select>51

52
<insert id="InsertPerson" parameterclass="Person" >53
<selectKey property="Id" type="post" resultClass="int">54
${selectKey}55
</selectKey> 56
insert into Person57
( PER_FIRST_NAME,58
PER_LAST_NAME,59
PER_BIRTH_DATE,60
PER_WEIGHT_KG,61
PER_HEIGHT_M)62
values63
(#FirstName#,#LastName#,#BirthDate#, #WeightInKilograms#, #HeightInMeters#)64
</insert>65
<update id="UpdatePerson"66
parameterclass="Person">67
<![CDATA[ update Person set68
PER_FIRST_NAME =#FirstName#,69
PER_LAST_NAME =#LastName#,70
PER_BIRTH_DATE =#BirthDate#,71
PER_WEIGHT_KG=#WeightInKilograms#,72
PER_HEIGHT_M=#HeightInMeters#73
where74
PER_ID = #Id# ]]>75
</update>76

77
78

79
<delete id="DeletePerson" parameterclass="Person">80
delete from Person81
where82
PER_ID = #Id#83
</delete>84
</statements>85
</sqlMap>86

87

可以看到,映射文件主要分为两个部分:模块配置和Statement配置。
模块配置包括:
1、typeAlias节点
定义了本映射文件中的别名,以避免过长变量值的反复书写,此例中通过typeAlias节点为类“IBatisNetDemo.Domain.Person”定义了一个别名“Person”,这样在本配置文件中的其他部分,需要引用“IBatisNetDemo.Domain.Person”类时,只需以其别名替代即可。
2、cacheModel节点
定义了本映射文件中使用的Cache机制:
|
<cacheModelid="person-cache"implementation="MEMORY" > <flushIntervalhours="24"/> <flushOnExecute statement="UpdateAccountViaInlineParameters"/> <flushOnExecute statement="UpdateAccountViaParameterMap"/> <propertyname="Type"value="Weak"/> </cacheModel> |
这里声明了一个名为“person-cache”的cacheModel,之后可以在Statement声明中对其进行引用:
|
<selectid="SelectAllPerson"resultMap="SelectAllResult" cacheModel=" person-cache"> select PER_ID, PER_FIRST_NAME, PER_LAST_NAME, PER_BIRTH_DATE, PER_WEIGHT_KG, PER_HEIGHT_M from PERSON </select> |
这表明对通过id为SelAllPerson的“Select Statement”获取的数据,使用CacheModel “person-cache”进行缓存。之后如果程序再次用此Satement进行数据查询。即直接从缓存中读取数据,而不需再去数据库查询。
CacheModel主要有几个配置点:
|
参数 |
描述 |
|
flushInterval |
设定缓存有效期,如果超过此设定值,则将此CacheModel缓存清空 |
|
CacheSize |
本Cachemodel中最大的数据对象数量 |
|
flushOnExecute |
指定执行特定的Statement时,将缓存清空。如UpdatePerson操作将更新数据库中用户信息,这将导致缓存中的数据对象与数据库中的实际数据发生偏差,因此必须将缓存清空以避免脏数据的出现。 |
3、resultMaps节点
resultMaps实现dotnet实体到数据库字段的映射配置:
|
<resultMapid="SelectAllResult"class="Person"> <resultproperty="Id"column="PER_ID" /> <resultproperty="FirstName"column="PER_FIRST_NAME" /> <resultproperty="LastName"column="PER_LAST_NAME" /> <resultproperty="BirthDate"column="PER_BIRTH_DATE" /> <resultproperty="WeightInKilograms"column="PER_WEIGHT_KG" /> <resultproperty="HeightInMeters"column="PER_HEIGHT_M" /> </resultMap> |
Statement配置:
Statement配置包含了数个与Sql Statement相关的节点,<statement>元素是一个通用的能够包容任意类型sql的元素。我们可以用更多细节的元素。
这些细节元素提供更好的错误检查以及一些更多的功能。(例如,一个插入函数能够返回数据库自动生成的key)。以下表格总结了声明类型元素以及他们的特性和属性。
|
Statement Element |
Attributes |
Child Elements |
Methods |
|
<statement> |
id parameterClass resultClass parameterMap resultMap cacheModel xmlResultName (Java only) |
All dynamic elements |
insert update delete All query methods |
|
<insert> |
id parameterClass parameterMap |
All dynamic elements <selectKey> <generate> (.NET only) |
insert update delete |
|
<update> |
id parameterClass parameterMap |
All dynamic elements <generate> (.NET only) |
insert update delete |
|
<delete> |
id parameterClass parameterMap |
All dynamic elements <generate> (.NET only) |
insert update delete |
|
<select> |
id parameterClass resultClass parameterMap resultMap cacheModel |
All dynamic elements <generate> (.NET only) |
All query methods |
|
<procedure> |
id parameterClass resultClass parameterMap resultMap xmlResultName (Java only) |
All dynamic elements |
insert update delete All query methods |
其中,statement最为通用,它可以代替其余的所有节点。除statement之外的节点对应于SQL中的同名操作(procedure对应存储过程)。使用Statement定义所有操作,缺乏直观性,建议在开发中根据操作目的,各自选用对应的节点名加以说明。一方面,使得配置文件更加直观,另一方面,也可以借助xsd对i节点声明进行更有针对性的检查,以避免配置上的失误。
|
<statement id=”statementName” [parameterMap=”nameOfParameterMap”] [parameterClass=”some.class.Name”] [resultMap=”nameOfResultMap”] [resultClass=”some.class.Name”] [cacheModel=”nameOfCache”] > select * from PRODUCT where PRD_ID = [?|#propertyName#] order by [$simpleDynamic$] </statement> |
其中“[ ]”包围的部分为可能出现的配置项,各参数说明见下表。具体的使用方法参见IBatisNet官方文档。
|
参数 |
描述 |
|
parameterMap |
参数映射,需结合parameterMap节点对映射关系加以定义,对于存储过程之外的statement而言,建议使用parameterClass作为参数配置方式,一方面避免了参数映射配置工作,另一方面其性能表现更加出色 |
|
parameterClass |
参数类。指定了参数类型的完整类名(包括命名空间),可以通过别名避免每次书写冗长的类名 |
|
resultMap |
结果映射,需结合resultMap节点对映射关系加以定义 |
|
resultClass |
结果类。指定了结果类型的完整类名(包括命名空间),可以通过别名避免每次书写冗长的类名 |
|
cacheModel |
Statement对应的Cache模块 |
一般而言,对于insert、update、delete、select语句,优先采用parameterClass和resultClass.。paremeterMap使用较少,而ResultMap则大多用于存储过程处理和查询。存储过程相对而言比较封闭(很多情况下需要调用现有的存储过程),其参数名和返回的数据字段命名往往不符合dotnet编程的命名规范)。使用resultMap建立字段名同Dotnet对象的属性之间的映射关系就非常有效。另一方面,由于通过ResultMap指定了字段名和字段类型,ibatisnet无需再通过ado.net来动态获取字段信息,在一定程度上也提升了性能。
下面特别说明一下ibatisnet对Stored Procedures的处理,iBatis数据映射把存储过程当成另外一种声明元素。示例演示了一个基于存储过程的简单数据映射。
<!-- Microsot SQL Server -->
<procedure id="SwapEmailAddresses" parameterMap="swap-params">
ps_swap_email_address
</procedure>
...
<parameterMap id="swap-params">
<parameter property="email1" column="First_Email" />
<parameter property="email2" column="Second_Email" />
</parameterMap>
<!-- Oracle with MS OracleClient provider -->
<procedure id="InsertCategory" parameterMap="insert-params">
prc_InsertCategory
</procedure>
...
<parameterMap id="insert-params">
<parameter property="Name" column="p_Category_Name"/>
<parameter property="GuidString" column="p_Category_Guid" dbType="VarChar"/>
<parameter property="Id" column="p_Category_Id" dbType="Int32" type="Int"/>
</parameterMap>
<!-- Oracle with ODP.NET 10g provider -->
<statement id="InsertAccount" parameterMap="insert-params">
prc_InsertAccount
</statement>
...
<parameterMap id="insert-params">
<parameter property="Id" dbType="Int32"/>
<parameter property="FirstName" dbType="VarChar2" size="32"/>
<parameter property="LastName" dbType="VarChar2" size="32"/>
<parameter property="EmailAddress" dbType="VarChar2" size="128"/>
</parameterMap>
|
示例是调用存储过程swapEmailAddress的时候将会在数据库表的列和两个email地址之间交换数据,参数对象亦同。参数对象仅在属性被设置成INOUT或者OUT的时候才会被修改。否则,他们将不会被修改。当然,不可变得参数对象是不会被修改的,比如string.
.Net中,parameterMap属性是必须的。DBType,参数方向,大小由框架自动发现的。(使用CommandBuilder实现的)


浙公网安备 33010602011771号