IbatisNet开发使用小结
一.?? 介紹
??平常做企業(yè)級(jí)應(yīng)用,需求變化是經(jīng)常的事,而很多基礎(chǔ)代碼重復(fù)也是很讓人頭疼的問(wèn)題。所以很多人會(huì)使用一些ORM框架來(lái)增強(qiáng)項(xiàng)目的可維護(hù)性、可擴(kuò)展性。IBatis.Net就是一個(gè)比較易用的ORM框架,使用起來(lái)較為方便、靈活。IBatis.Net是從Ibatis的Java版本移植過(guò)來(lái)的.NET版本。iBATIS作為一種獨(dú)特的Data Mapper,使用SQL映射的方式將對(duì)象持久化至關(guān)系型數(shù)據(jù)庫(kù)。簡(jiǎn)單的理解就是它將我們?cè)跀?shù)據(jù)訪問(wèn)層實(shí)現(xiàn)的C#邏輯代碼,變?yōu)橥ㄟ^(guò)關(guān)系數(shù)據(jù)庫(kù)與對(duì)象的映射,將SQL邏輯放到外部的XML配置文件中,以方便以后的維護(hù)。
?? 這個(gè)框架有兩個(gè)主要的組成部分,一個(gè)是SQL Maps,另一個(gè)是Data Access Objects。Sql Maps是這個(gè)框架的核心部分,通過(guò)使用Sql Maps你可以顯著的節(jié)約數(shù)據(jù)庫(kù)操作的代碼量。SQL Maps使用一個(gè)簡(jiǎn)單的XML文件來(lái)實(shí)現(xiàn)從實(shí)體到SQL statements的映射。使用DAO,封裝了對(duì)數(shù)據(jù)的訪問(wèn),你可以動(dòng)態(tài)配置你的應(yīng)用程序來(lái)訪問(wèn)不同的實(shí)體存儲(chǔ)機(jī)制。隱藏持久性層實(shí)現(xiàn)的細(xì)節(jié),Data Access Objects允許你通過(guò)一個(gè)簡(jiǎn)單接口的來(lái)操作數(shù)據(jù)。
? ?
二.?? 準(zhǔn)備工作
下面先讓我們來(lái)動(dòng)手實(shí)踐一下,看看如何使用和調(diào)用IbatisNet。
1.? 下載IbatisNet軟件包: http://ibatis.apache.org/dotnetdownloads.cgi
| iBATIS.NET Downloads
| ?? |
| ?? |
官方網(wǎng)站還提供了一個(gè)示例項(xiàng)目:NPetShop Example Application
? ?
2.? 建立測(cè)試數(shù)據(jù)庫(kù),并在數(shù)據(jù)庫(kù)中創(chuàng)建一個(gè)Person 表:
| 字段 | 類型 | 大小 |
| PER_ID | int | 4 |
| PER_FIRST_NAME | nvarchar | 40 |
| PER_LAST_NAME | nvarchar | 40 |
| PER_BIRTH_DATE | DateTime | 8 |
| PER_WEIGHT_KG | float | 8 |
| PER_HEIGHT_M | float | 8 |
? ?
三.?? 開發(fā)步驟
1.邏輯結(jié)構(gòu)
???
2.建立項(xiàng)目
打開VS.NET,新建一個(gè)"ASP.NET Web應(yīng)用程序"項(xiàng)目。
? ?
3.添加引用
在項(xiàng)目中添加下面dll的引用:
IBatisNet.Common.dll
IBatisNet.DataMapper.dll
IBatisNet.DataAccess.dll
? ?
4.在項(xiàng)目中,添加配置文件 SqlMap.config
該文件為IBatis.net默認(rèn)的配置文件,不能缺少,當(dāng)然可以不必是Sql.config,但是如果改為其他的名字的話需要在前臺(tái)代碼中說(shuō)明,請(qǐng)參考下面的內(nèi)容providers.config:該文件必須存在,并且不能改變它的文件名,該文件描述了如何連接數(shù)據(jù)庫(kù),無(wú)須配置
結(jié)合上面示例中的IbatisNet配置文件,下面對(duì)配置文件中各節(jié)點(diǎn)的說(shuō)明:
| <?xml version="1.0" encoding="utf-8"?> <sqlMapConfig xmlns="http://ibatis.apache.org/dataMapper" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > ? ? <!-- 常量屬性,通過(guò)單獨(dú)文件properties.config加載--> <properties resource="properties.config"/> <!-- 常量屬性,通過(guò)程序集資源中 加載 <properties embedded="database.config, IBatisNetDemo"/>--> ???? ? <settings> ????<setting useStatementNamespaces="${useStatementNamespaces}"/> ????<setting cacheModelsEnabled="true"/> ????<setting validateSqlMap="false"/> </settings> ? ? <!-- 數(shù)據(jù)驅(qū)動(dòng)提供類配置文件的路徑和文件名 --> <providers resource="providers.config"/> ? ? <!-- 設(shè)置數(shù)據(jù)庫(kù)連接信息????--> <database> <provider name="${provider}"/> <dataSource name="IBatisNetTest" connectionString="${connectionString}"/> </database> ? ? <!-- 指定項(xiàng)目?jī)?nèi)映射的文件的位置--> <sqlMaps> <!-- 從程序集中 <sqlMap embedded="${root}Person.xml,${assembly}" />--> <!-- 從文件中--> <sqlMap resource="@Maps/Person.xml" /> ????</sqlMaps> </sqlMapConfig> |
? ?
詳細(xì)說(shuō)明:
(1) properties節(jié)點(diǎn)
可以根據(jù)需要配置一些常量屬性。如果這些屬性有很多的話可以單獨(dú)寫一個(gè)文件里面,再通過(guò)resource(或url, embedded分別是引用url和編譯在程序中的資源文件)屬性引用進(jìn)來(lái)。
? ?
properties 節(jié)點(diǎn)參數(shù)
| 參數(shù) | 描述 |
| resource | 指定the properties文件從application的根目錄進(jìn)行加載 resource="properties.config" |
| url | 指定the properties文件從文件的絕對(duì)路徑進(jìn)行加載 url="c:/Web/MyApp/Resources/properties.config" 或者 url="file://c:/Web/MyApp/Resources/properties.config" |
| embedded | 指定文件可以作為程序集的資源文件進(jìn)行加載' embedded=" database.config, IBatisNetDemo" |
? ?
上面例子中properties.config文件的配置如下:
| <?xml version="1.0" encoding="utf-8" ?> <settings> ????<!—應(yīng)用程序和配置屬性設(shè)置--> ????<add key="provider" value="sqlServer2.0" /> ????<add key="connectionString"???? value="server=127.0.0.1;database=TVSystem;uid=sa;pwd=1" /> ????<add key="root" value="IBatisNetTest.Maps." /> ????<add key="assembly" value="IBatisNetTest" /> ? <add key="userid" value="sa" /> <add key="password" value="" /> <add key="database" value="Northwind" /> <add key="datasource" value="localhost" /> <add key="selectKey" value="select @@IDENTITY as value" /> <add key="directory" value="Maps" /> <add key="useStatementNamespaces" value="false" /> </settings> |
? ?
下面解釋一下這個(gè)文件的節(jié)點(diǎn)參數(shù)
properties.config節(jié)點(diǎn)參數(shù)
| 參數(shù) | 描述 |
| key | 定義key (variable) 名字 key="username" |
| value | 定義DataMapper 中使用的 key的值 value="mydbuser" |
? ?
(2)?setting節(jié)點(diǎn)
Setting節(jié)點(diǎn)參數(shù)
| 參數(shù) | 描述 |
| cacheModelsEnabled | 是否啟用sqlMap上的緩存機(jī)制 Example: cacheModelsEnabled="true" Default: true (enabled) |
| useStatementNamespaces | 是否使用Satement命名空間,這里的命名空間指的是映射文件中sqlMap節(jié)點(diǎn)的namespace屬性,如上例中針對(duì)Person表的映射文件sqlMap節(jié)點(diǎn) <sqlMap namespace="Person" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance> 這里,指定了此sqlMap節(jié)點(diǎn)下定義的操作均叢屬于"Person"命名空間在useStatementNamespaces="true"的情況下,Statement調(diào)用需追加命名空間,如:sqlMap.Update("Person.UpdatePerson",person);否則直接通過(guò)Statement名稱調(diào)用即可,如sqlMap.Update("UpdatePerson",person);但請(qǐng)注意此時(shí)需要保證所有映射文件中,statement定義無(wú)重名 Example: useStatementNamespaces="false" Default: false (disabled) |
| validateSqlMap | 是配置要不要啟示SqlMapConfig.xsd schema驗(yàn)證映射文件. Example: validateSqlMap="false" Default: false (disabled) |
? ?
(3)?provider節(jié)點(diǎn)
配置數(shù)據(jù)驅(qū)動(dòng)提供類配置文件的路徑和文件名,通過(guò)resource(或url, embedded分別是引用url和編譯在程序中的資源文件)屬性引用進(jìn)來(lái),參數(shù)的含義同properties。
ADO.NET是通過(guò)數(shù)據(jù)訪問(wèn)提供程序(Provider)訪問(wèn)數(shù)據(jù)庫(kù)。IBatisNet使用的是插件式結(jié)構(gòu)來(lái)使用這些數(shù)據(jù)庫(kù)提供程序,每一個(gè)Provider對(duì)應(yīng)于providers.config文件中定義的一個(gè)provider項(xiàng)。1.3版本的Provider.config文件中定義了已經(jīng)實(shí)現(xiàn)的16個(gè)provider,通過(guò)設(shè)置這個(gè)文件中的幾個(gè)參數(shù)來(lái)決定使用哪個(gè)數(shù)據(jù)庫(kù)提供程序。
????????? sqlServer1.0 - Microsoft SQL Server 7.0/2000 provider available with .NET Framework 1.0
????????? sqlServer1.1 -Microsoft SQL Server 7.0/2000 provider available with .NET Framework 1.1
????????? sqlServer2.0 - Microsoft SQL server 7.0/2000/2005 provider available with .NET Framework 2.0
????????? OleDb1.1 - OleDb provider available with .NET Framework 1.1
????????? Odbc1.1 - Odbc provider available with .NET Framework 1.1
????????? oracle9.2 - Oracle provider V9.2.0.401
????????? oracle10.1 - Oracle provider V10.1.0.301
????????? oracleClient1.0 - MS Oracle provider V1.0.5 available with .NET Framework 1.1
????????? ByteFx - ByteFx MySQL provider V0.7.6.15073
????????? MySql - MySQL provider V1.0.4.20163
????????? SQLite3 - SQLite.NET provider V0.21.1869.3794
????????? Firebird1.7 - Firebird SQL .NET provider V1.7.0.33200
????????? PostgreSql0.7 - Npgsql provider V0.7.0.0
????????? PostgreSql0.7.1 - Npgsql provider V0.7.1.0
????????? iDb2.10 - IBM DB2 iSeries provider V10.0.0.0
????????? Informix -- informix NET Provider, 2.81.0.0
提供程序要求安裝相關(guān)類庫(kù),每一個(gè)provider 元素都有"enabled" 屬性來(lái)控制是否啟用這個(gè)providers. 一個(gè)provider 可以通過(guò) "default"屬性標(biāo)識(shí)為默認(rèn)的提供程序。
? ?
(4)?database節(jié)點(diǎn)
數(shù)據(jù)庫(kù)的信息,包括使用哪些數(shù)據(jù)庫(kù)驅(qū)動(dòng)和數(shù)據(jù)連接字符串的配置。
Database節(jié)點(diǎn)參數(shù)
| 參數(shù) | 描述 |
| provider | 數(shù)據(jù)庫(kù)訪問(wèn)所使用的provider.config文件定義的provider |
| dataSource | 特定的數(shù)據(jù)庫(kù)連接字符串 |
? ?
(5)?typeHandler節(jié)點(diǎn)
定義數(shù)據(jù)庫(kù)類型到dotnet數(shù)據(jù)類型的處理,不同的數(shù)據(jù)庫(kù)都有一些特殊的數(shù)據(jù)庫(kù)字段類型需要特殊處理,就可以通過(guò)這個(gè)功能實(shí)現(xiàn)。比如說(shuō)Blob字段在不同的數(shù)據(jù)庫(kù)中處理不一樣。大家可以去看看Ibatisnet源代碼就清楚這個(gè)功能的實(shí)現(xiàn)原理,對(duì)于我們的設(shè)計(jì)會(huì)有很大的啟發(fā)
(6)?sqlMaps節(jié)點(diǎn)
sqlMap節(jié)點(diǎn)指定了映射文件的位置,配置中可以出現(xiàn)多個(gè)sqlMap節(jié)點(diǎn),以指定項(xiàng)目?jī)?nèi)所包含的所有映射文件。
? ?
? ?
5.創(chuàng)建實(shí)體類
定義Person的實(shí)體類,該對(duì)象類將與數(shù)據(jù)庫(kù)進(jìn)行映射。
| [Serializable] public class Person { private int id; private string firstName; private string lastName; private DateTime? birthDate; private double? weightInKilograms; private double? heightInMeters; public Person() { } public int Id { get { return id; } set { id = value; } } public string FirstName { get { return firstName; } set { firstName = value; } } public string LastName { get { return lastName; } set { lastName = value; } } public DateTime? BirthDate { get { return birthDate; } set { birthDate = value; } } public double? WeightInKilograms { get { return weightInKilograms; } set { weightInKilograms = value; } } public double? HeightInMeters { get { return heightInMeters; } set { heightInMeters = value; } } } |
? ?
? ?
6.添加Person的映射文件Person.xml
相對(duì)于Nhibernate等ORM實(shí)現(xiàn)來(lái)說(shuō),IBatisnet的映射配置更為直接,下面是配置文件內(nèi)容:
| <?xml version="1.0" encoding="utf-8" ?> <sqlMap namespace="Person" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > ? ? ????<!--模塊配置--> ????<alias> ????????<typeAlias alias="Person" type="IBatisNetLib.Person,IBatisNetLib" /> ????</alias> ????<resultMaps> ????????<resultMap id="SelectAllResult" class="Person"> ????????????<result property="Id" column="PER_ID" /> ????????????<result property="FirstName" column="PER_FIRST_NAME" /> ????????????<result property="LastName" column="PER_LAST_NAME" /> ????????????<result property="BirthDate" column="PER_BIRTH_DATE" /> ????????????<result property="WeightInKilograms" column="PER_WEIGHT_KG" /> ????????????<result property="HeightInMeters" column="PER_HEIGHT_M" /> ????????</resultMap> ????</resultMaps> ???????? <!--statement配置--> ????<statements> <select id="Exists" resultClass="int" parameterclass="int"> select count(1) from PERSON where PER_ID = #value# </select> ? ????????<insert id="InsertPerson" parameterclass="Person" > ????????????<selectKey property="Id" type="post" resultClass="int"> ????????????????${selectKey} ????????????</selectKey> ????????????insert into Person ????????????( PER_FIRST_NAME, ????????????PER_LAST_NAME, ????????????PER_BIRTH_DATE, ????????????PER_WEIGHT_KG, ????????????PER_HEIGHT_M)values(#FirstName#,#LastName#,#BirthDate#, #WeightInKilograms#, #HeightInMeters#) ????????</insert> ? ? ????????<update id="UpdatePerson" ???????????????????? parameterclass="Person"> ????????????<![CDATA[ update Person set PER_FIRST_NAME =#FirstName#, PER_LAST_NAME =#LastName#, PER_BIRTH_DATE =#BirthDate#, PER_WEIGHT_KG=#WeightInKilograms#, PER_HEIGHT_M=#HeightInMeters# where PER_ID = #Id# ]]> ????????</update> ? ? ????????<delete id="DeletePerson" parameterclass="Person"> ????????????delete from Person where PER_ID = #Id# ????????</delete> ? <select id="SelectAllPerson" resultMap="SelectAllResult"> Select * from PERSON </select> ? ? <select id="SelectByPersonId" resultMap="SelectAllResult" resultClass="Person" parameterClass="int"> select PER_ID, PER_FIRST_NAME, PER_LAST_NAME, PER_BIRTH_DATE, PER_WEIGHT_KG, PER_HEIGHT_M from PERSON where PER_ID = #value# </select> </statements>???? </sqlMap> |
? ?
可以看到,映射文件主要分為兩個(gè)部分:模塊配置 和 Statement配置。
模塊配置包括:
(1)Type Alias節(jié)點(diǎn)
定義了本映射文件中的別名,以避免過(guò)長(zhǎng)變量值的反復(fù)書寫,此例中通過(guò)typeAlias節(jié)點(diǎn)為類"IBatisNetDemo.Domain.Person"定義了一個(gè)別名"Person",這樣在本配置文件中的其他部分,需要引用"IBatisNetDemo.Domain.Person"類時(shí),只需以其別名替代即可。
? ?
(2)cacheModel節(jié)點(diǎn)
定義了本映射文件中使用的Cache機(jī)制:
| <cacheModel id="person-cache" implementation="MEMORY" > <flushInterval hours="24"/> <flushOnExecute statement="UpdateAccountViaInlineParameters"/> <flushOnExecute statement="UpdateAccountViaParameterMap"/> <property name="Type" value="Weak"/> </cacheModel> |
這里聲明了一個(gè)名為"person-cache"的cacheModel,之后可以在Statement聲明中對(duì)其進(jìn)行引用:
| <select id="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> |
這表明對(duì)通過(guò)id為SelAllPerson的"Select Statement"獲取的數(shù)據(jù),使用CacheModel "person-cache"進(jìn)行緩存。之后如果程序再次用此Satement進(jìn)行數(shù)據(jù)查詢。即直接從緩存中讀取數(shù)據(jù),而不需再去數(shù)據(jù)庫(kù)查詢。
CacheModel主要有幾個(gè)配置點(diǎn):
| 參數(shù) | 描述 |
| flushInterval | 設(shè)定緩存有效期,如果超過(guò)此設(shè)定值,則將此CacheModel緩存清空 |
| CacheSize | 本Cachemodel中最大的數(shù)據(jù)對(duì)象數(shù)量 |
| flushOnExecute | 指定執(zhí)行特定的Statement時(shí),將緩存清空。如UpdatePerson操作將更新數(shù)據(jù)庫(kù)中用戶信息,這將導(dǎo)致緩存中的數(shù)據(jù)對(duì)象與數(shù)據(jù)庫(kù)中的實(shí)際數(shù)據(jù)發(fā)生偏差,因此必須將緩存清空以避免臟數(shù)據(jù)的出現(xiàn)。 |
? ?
(3)resultMaps節(jié)點(diǎn)
resultMaps實(shí)現(xiàn)dotnet實(shí)體到數(shù)據(jù)庫(kù)字段的映射配置:
| <resultMap id="SelectAllResult" class="Person"> <result property="Id" column="PER_ID" /> <result property="FirstName" column="PER_FIRST_NAME" /> <result property="LastName" column="PER_LAST_NAME" /> <result property="BirthDate" column="PER_BIRTH_DATE" /> <result property="WeightInKilograms" column="PER_WEIGHT_KG" /> <result property="HeightInMeters" column="PER_HEIGHT_M" /> </resultMap> |
? ?
(4)Statement配置:
?⑴ ID
指定了操作ID,之后我們可以在代碼中通過(guò)指定操作id 來(lái)執(zhí)行此節(jié)點(diǎn)所定義的操作,如:
SqlMap.Update("UpdatePerson", person);
ID設(shè)定使得在一個(gè)配置文件中定義兩個(gè)同名節(jié)點(diǎn)成為可能(兩個(gè)update節(jié)點(diǎn),以不同id區(qū)分)
⑵ parameterClass
指定了操作所需的參數(shù)類型,此例中update 操作以IBatisNetDemo.Domain.Person類型的對(duì)象作為參數(shù),目標(biāo)是將提供的Person實(shí)例更新到數(shù)據(jù)庫(kù)。
parameterClass="Person"中,user為"IBatisNetDemo.Domain.Person"
類的別名,別名可通過(guò)typeAlias節(jié)點(diǎn)指定,如示例配置文件中的:
<typeAlias alias="Person" type="IBatisNetDemo.Domain.Person,IBatisNetDemo" />
? ?
⑶ <![CDATA[……]]>
通過(guò)<![CDATA[……]]>節(jié)點(diǎn),可以避免SQL 中與XML 規(guī)范相沖突的字符對(duì)XML映射文件的合法性造成影響。
⑷ 執(zhí)行更新操作的SQL,這里的SQL 即實(shí)際數(shù)據(jù)庫(kù)支持的SQL 語(yǔ)句,將由IBatisNet填入?yún)?shù)后交給數(shù)據(jù)庫(kù)執(zhí)行。
⑸ SQL中所需的用戶名參數(shù),"# FirstName #"在運(yùn)行期會(huì)由傳入的Person對(duì)象的FirstName屬性填充。
⑹ SQL 中所需的用戶性別參數(shù)"# LastName #",將在運(yùn)行期由傳入的user 對(duì)象的LastName屬性填充。
⑺ SQL中所需的條件參數(shù)"#id#",將在運(yùn)行期由傳入的Person對(duì)象的Person屬性填充。
對(duì)于這個(gè)示例,IBatisNet在運(yùn)行期會(huì)讀取id 為"UpdatePerson"的update節(jié)點(diǎn)的SQL定義,并調(diào)用指定的user對(duì)象的對(duì)應(yīng)getter方法獲取屬性值,并用此屬性值,對(duì)SQL中的參數(shù)進(jìn)行填充后提交數(shù)據(jù)庫(kù)執(zhí)行。
? ?
? ?
Statement配置包含了數(shù)個(gè)與Sql Statement相關(guān)的節(jié)點(diǎn),<statement>元素是一個(gè)通用的能夠包容任意類型sql的元素。我們可以用更多細(xì)節(jié)的元素。
這些細(xì)節(jié)元素提供更好的錯(cuò)誤檢查以及一些更多的功能。(例如,一個(gè)插入函數(shù)能夠返回?cái)?shù)據(jù)庫(kù)自動(dòng)生成的key)。以下表格總結(jié)了聲明類型元素以及他們的特性和屬性。
| 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最為通用,它可以代替其余的所有節(jié)點(diǎn)。除statement之外的節(jié)點(diǎn)對(duì)應(yīng)于SQL中的同名操作(procedure對(duì)應(yīng)存儲(chǔ)過(guò)程)。使用Statement定義所有操作,缺乏直觀性,建議在開發(fā)中根據(jù)操作目的,各自選用對(duì)應(yīng)的節(jié)點(diǎn)名加以說(shuō)明。一方面,使得配置文件更加直觀,另一方面,也可以借助xsd對(duì)i節(jié)點(diǎn)聲明進(jìn)行更有針對(duì)性的檢查,以避免配置上的失誤。
? ?
| <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> |
? ?
其中"[ ]"包圍的部分為可能出現(xiàn)的配置項(xiàng),各參數(shù)說(shuō)明見下表。具體的使用方法參見IBatisNet官方文檔。
| 參數(shù) | 描述 |
| parameterMap | 參數(shù)映射,需結(jié)合parameterMap節(jié)點(diǎn)對(duì)映射關(guān)系加以定義,對(duì)于存儲(chǔ)過(guò)程之外的statement而言,建議使用parameterClass作為參數(shù)配置方式,一方面避免了參數(shù)映射配置工作,另一方面其性能表現(xiàn)更加出色 |
| parameterClass | 參數(shù)類。指定了參數(shù)類型的完整類名(包括命名空間),可以通過(guò)別名避免每次書寫冗長(zhǎng)的類名 |
| resultMap | 結(jié)果映射,需結(jié)合resultMap節(jié)點(diǎn)對(duì)映射關(guān)系加以定義 |
| resultClass | 結(jié)果類。指定了結(jié)果類型的完整類名(包括命名空間),可以通過(guò)別名避免每次書寫冗長(zhǎng)的類名 |
| cacheModel | Statement對(duì)應(yīng)的Cache模塊 |
? ?
一般而言,對(duì)于insert、update、delete、select語(yǔ)句,優(yōu)先采用parameterClass和resultClass.。paremeterMap使用較少,而ResultMap則大多用于存儲(chǔ)過(guò)程處理和查詢。存儲(chǔ)過(guò)程相對(duì)而言比較封閉(很多情況下需要調(diào)用現(xiàn)有的存儲(chǔ)過(guò)程),其參數(shù)名和返回的數(shù)據(jù)字段命名往往不符合dotnet編程的命名規(guī)范)。使用resultMap建立字段名同Dotnet對(duì)象的屬性之間的映射關(guān)系就非常有效。另一方面,由于通過(guò)ResultMap指定了字段名和字段類型,ibatisnet無(wú)需再通過(guò)ado.net來(lái)動(dòng)態(tài)獲取字段信息,在一定程度上也提升了性能。
IBatisNet開發(fā)使用小結(jié) 之二
?本文示例項(xiàng)目源碼下載
?動(dòng)軟代碼生成器新增對(duì)IBatisNet的代碼生成插件
四.?? IBatisNet組件使用
1.? DomSqlMapBuilder
DomSqlMapBuilder,其作用是根據(jù)配置文件創(chuàng)建SqlMap實(shí)例。可以通過(guò)這個(gè)組件從Stream, Uri, FileInfo, or XmlDocument instance 來(lái)讀取sqlMap.config文件。?
2.? SqlMap
SqlMapper是IBatisnet的核心組件,提供數(shù)據(jù)庫(kù)操作的基礎(chǔ)平臺(tái)。所有的操作均通過(guò)SqlMapper實(shí)例完成。SqlMapper可通過(guò)DomSqlMapBuilder創(chuàng)建。
這個(gè)例子中我們可以將所有的配置文件按照嵌入資源文件方式存放,從程序集去加載sqlmap.config文件。也可以直接以文件方式加載sqlmap.config。?
| /// <summary> /// IsqlMapper實(shí)例 /// </summary> /// <returns></returns> public static ISqlMapper sqlMap ; private string fileName = "sqlMap.Config"; public BaseSqlMapDao() { //從程序集資源中加載 //Assembly assembly = Assembly.Load("IBatisNetDemo"); //Stream stream = assembly.GetManifestResourceStream("IBatisNetDemo.sqlmap.config"); //DomSqlMapBuilder builder = new DomSqlMapBuilder(); //sqlMap = builder.Configure(stream); ? ? //從文件加載創(chuàng)建實(shí)例 DomSqlMapBuilder builder = new DomSqlMapBuilder(); sqlMap = builder.Configure(fileName); } |
? ?
SqlMap是線程安全的,也就是說(shuō),在一個(gè)應(yīng)用中,可以共享一個(gè)SqlMap實(shí)例。
SqlMap提供了眾多數(shù)據(jù)操作方法,下面是一些常用方法的示例,具體說(shuō)明文檔參見 ibatis net doc,或者ibatisnet的官方開發(fā)手冊(cè)。?
3.? SqlMap基本操作示例?
例1:數(shù)據(jù)寫入操作(insert、update、delete)
| SqlMap.BeginTransaction(); Person person = new Person(); Person.FirstName = "li"; Person.LastName = "tianping"; int Id = (int) SqlMap.Insert("InsertPerson", person); SqlMap.CommitTransaction(); |
?例2:數(shù)據(jù)查詢:
| Int Id = 1; Person person = SqlMap.QueryForObject<Person>("", Id); return person; |
?例3:執(zhí)行批量查詢(Select)
| IList<Person> list = null; list = SqlMap.QueryForList<Person>("SelectAllPerson", null); return list; |
?例4:查詢指定范圍內(nèi)的數(shù)據(jù)(Select)
| IList<Person> list = null; list = SqlMap.QueryForList<Person>("SelectAllPerson", null, 0, 40); return list; |
?例5:結(jié)合RowDelegate進(jìn)行查詢:
| 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); |
?4.? 存儲(chǔ)過(guò)程操作
下面特別說(shuō)明一下ibatisnet對(duì)Stored Procedures的處理,iBatis數(shù)據(jù)映射把存儲(chǔ)過(guò)程當(dāng)成另外一種聲明元素。示例演示了一個(gè)基于存儲(chǔ)過(guò)程的簡(jiǎn)單數(shù)據(jù)映射。?
| <!-- 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> ?? |
? ?
示例是調(diào)用存儲(chǔ)過(guò)程swapEmailAddress的時(shí)候?qū)?huì)在數(shù)據(jù)庫(kù)表的列和兩個(gè)email地址之間交換數(shù)據(jù),參數(shù)對(duì)象亦同。參數(shù)對(duì)象僅在屬性被設(shè)置成INOUT或者OUT的時(shí)候才會(huì)被修改。否則,他們將不會(huì)被修改。當(dāng)然,不可變得參數(shù)對(duì)象是不會(huì)被修改的,比如string.
.Net中,parameterMap屬性是必須的。DBType,參數(shù)方向,大小由框架自動(dòng)發(fā)現(xiàn)的。(使用CommandBuilder實(shí)現(xiàn)的)。
? ?
五.?? IBatisNet封裝類:BaseSqlMapDao
為了日后的重復(fù)使用和代碼簡(jiǎn)潔,我們可以像DbHelperSQL一樣,對(duì)SqlMap的各種操作進(jìn)行封裝。
? ?
| using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.IO; using System.Web; using System.Reflection; using IBatisNet.Common; using IBatisNet.Common.Pagination; using IBatisNet.DataMapper; using IBatisNet.DataMapper.Exceptions; using IBatisNet.DataMapper.Configuration; namespace IBatisNetLib { /// <summary> /// 基于IBatisNet的數(shù)據(jù)訪問(wèn)基類 /// </summary> public class BaseSqlMapDao { /// <summary> /// IsqlMapper實(shí)例 /// </summary> /// <returns></returns> public static ISqlMapper sqlMap; #region 構(gòu)造ISqlMapper private string fileName = "sqlMap.Config"; public BaseSqlMapDao() { //從程序集中加載 //Assembly assembly = Assembly.Load("IBatisNetDemo"); //Stream stream = assembly.GetManifestResourceStream("IBatisNetDemo.sqlmap.config"); //DomSqlMapBuilder builder = new DomSqlMapBuilder(); //sqlMap = builder.Configure(stream); ? ? //從文件加載創(chuàng)建實(shí)例 DomSqlMapBuilder builder = new DomSqlMapBuilder(); sqlMap = builder.Configure(fileName); } #endregion ? /// <summary> /// 是否存在 /// </summary> /// <param name="tableName">表名</param> /// <returns></returns> protected bool ExecuteExists(string statementName, object parameterObject) { try { object obj = sqlMap.QueryForObject(statementName, parameterObject); int cmdresult; if ((Object.Equals(obj, null)) || (obj == null)) { cmdresult = 0; } else { cmdresult = int.Parse(obj.ToString()); } if (cmdresult == 0) { return false; } else { return true; } } catch (Exception e) { throw (e); } } ? /// <summary> /// 執(zhí)行添加 /// </summary> /// <param name="statementName">操作名</param> /// <param name="parameterObject">參數(shù)</param> protected object ExecuteInsert(string statementName, object parameterObject) { try { return sqlMap.Insert(statementName, parameterObject); } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for insert. Cause: " + e.Message, e); } } /// <summary> /// 執(zhí)行添加,返回自動(dòng)增長(zhǎng)列 /// </summary> /// <param name="statementName">操作名</param> /// <param name="parameterObject">參數(shù)</param> /// <returns>返回自動(dòng)增長(zhǎng)列</returns> protected int ExecuteInsertForInt(string statementName, object parameterObject) { try { object obj=sqlMap.Insert(statementName, parameterObject); if (obj != null) { return Convert.ToInt32(obj); } else { return 0; } } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for insert. Cause: " + e.Message, e); } } ? ? /// <summary> /// 執(zhí)行修改 /// </summary> /// <param name="statementName">操作名</param> /// <param name="parameterObject">參數(shù)</param> /// <returns>返回影響行數(shù)</returns> protected int ExecuteUpdate(string statementName, object parameterObject) { try { return sqlMap.Update(statementName, parameterObject); } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for update. Cause: " + e.Message, e); } } ? ? /// <summary> /// 執(zhí)行刪除 /// </summary> /// <param name="statementName">操作名</param> /// <param name="parameterObject">參數(shù)</param> /// <returns>返回影響行數(shù)</returns> protected int ExecuteDelete(string statementName, object parameterObject) { try { return sqlMap.Delete(statementName, parameterObject); } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for delete. Cause: " + e.Message, e); } } ? ? /// <summary> /// 得到列表 /// </summary> /// <typeparam name="T">實(shí)體類型</typeparam> /// <param name="statementName">操作名稱,對(duì)應(yīng)xml中的Statement的id</param> /// <param name="parameterObject">參數(shù)</param> /// <returns></returns> protected IList<T> ExecuteQueryForList<T>(string statementName, object parameterObject) { try { return sqlMap.QueryForList<T>(statementName, parameterObject); } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for list. Cause: " + e.Message, e); } } ? ? /// <summary> /// 得到指定數(shù)量的記錄數(shù) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="statementName"></param> /// <param name="parameterObject">參數(shù)</param> /// <param name="skipResults">跳過(guò)的記錄數(shù)</param> /// <param name="maxResults">最大返回的記錄數(shù)</param> /// <returns></returns> protected IList<T> ExecuteQueryForList<T>(string statementName, object parameterObject, int skipResults, int maxResults) { try { return sqlMap.QueryForList<T>(statementName, parameterObject, skipResults, maxResults); } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for list. Cause: " + e.Message, e); } } ? ? /// <summary> /// 得到分頁(yè)的列表 /// </summary> /// <param name="statementName">操作名稱</param> /// <param name="parameterObject">參數(shù)</param> /// <param name="pageSize">每頁(yè)記錄數(shù)</param> /// <returns></returns> protected IPaginatedList ExecuteQueryForPaginatedList(string statementName, object parameterObject, int pageSize) { try { return sqlMap.QueryForPaginatedList(statementName, parameterObject, pageSize); } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for paginated list. Cause: " + e.Message, e); } } ? ? /// <summary> /// 查詢得到對(duì)象的一個(gè)實(shí)例 /// </summary> /// <typeparam name="T">對(duì)象type</typeparam> /// <param name="statementName">操作名</param> /// <param name="parameterObject">參數(shù)</param> /// <returns></returns> protected T ExecuteQueryForObject<T>(string statementName, object parameterObject) { try { return sqlMap.QueryForObject<T>(statementName, parameterObject); } catch (Exception e) { throw new DataMapperException("Error executing query '" + statementName + "' for object. Cause: " + e.Message, e); } } } } |
? ?
????調(diào)用該基類實(shí)現(xiàn)映射文件的數(shù)據(jù)訪問(wèn)代碼:
| using System; using System.Collections.Generic; using System.Text; namespace IBatisNetLib { public class PersonService : BaseSqlMapDao { public PersonService() { } /// <summary> /// 是否存在該記錄 /// </summary> public bool Exists(object Id) { return ExecuteExists("Exists", Id); } public void Insert(Person person) { ExecuteInsert("InsertPerson", person); } public void Update(Person person) { ExecuteUpdate("UpdatePerson", person); } public void Delete(Person person) { ExecuteDelete("DeletePerson", person); } public IList<Person> GetAllPerson() { IList<Person> list = null; list = ExecuteQueryForList<Person>("SelectAllPerson", null); return list; } public Person GetPerson(object Id) { Person person = ExecuteQueryForObject<Person>("SelectByPersonId", Id); return person; } } } |
??
轉(zhuǎn)載于:https://www.cnblogs.com/asks/p/4098225.html
總結(jié)
以上是生活随笔為你收集整理的IbatisNet开发使用小结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: webkit webApp 开发技术要点
- 下一篇: c# C++接口封装 汽车模拟仿真