iBatis.net技術實踐
隨著大數據技術的興起和快速發展,人們更多的開始關註HDFS、HBase、Hive等技術。但是談到強一致性,我們又不得不回歸現實,只能繼續沿用RDBMS存儲強一致性的數據。我們日常接觸到的絕大多數的應用(從App到遊戲,從互聯網應用到SAP)都是基於數據的,應用程序執行的過程也是不斷進行數據處理的過程,而應用的設計是面向對象的,數據庫更多是面向數據的,兩種不同思維造成系統理解、設計的復雜性。同時隨著業務復雜度的不斷提高,對數據庫的依賴也不斷增加,逐漸造成系統與數據庫耦合過於緊密。
隨著面向對象、系統解耦的要求,我們希望能有一種技術實現將數據庫結構轉化成易於理解的程序數據結構。通過對程序數據的處理,轉化為對數據庫的操作。而這正是ORM(對象關系映射object Relational Mapping)的一個理論基礎。
ORM方法論基於三個核心原則:
簡單性:以最基本的形式建模數據。
傳達性:數據庫結構被任何人都能理解的語言文檔化。
精確性:基於數據模型創建正確標準化了的結構。
一、ORM與IBatis
早些年在Java領域有一個非常知名的框架SSH(Spring + Struts +Hibernate)。他們各自承擔這不同的職責,實現了表現層、業務層和數據持久化層分離,降低了各層耦合。其中Hibernate則主要是實現了業務層與數據化持久層的解耦。Hibernate建立的理論基礎是ORM。它是建立將面向對象的數據轉化和操作映射為數據持久化操作的一種技術。
在ORM的領域中除了Hibernate還有很多其他框架。例如EntityFrameword、IBatis等。我們今天要介紹的就是IBatis,這個被稱為“半自動化”的ORM框架。
要介紹IBatis首先要說一下“半自動化”這個定語。之所有成IBatis為“半自動化”,是相對於Hibernate而言的。Hibernate可以實現不編寫Sql語句實現將業務數據操作轉化為數據庫操作。IBatis沒有像Hibernate那樣進行全面的封裝,它並沒有拋棄Sql語句,甚至它不會減少Sql語句的編寫量,它只是提供了一種將Sql語句與系統分離的方式,這也給我們留下了足夠了空間發揮Sql的強大語法。
二、IBatis原理
IBatis的基本原理的理解可以從理解官方文檔中的這個圖開始
IBatis以SqlMap為核心,將輸入參數、輸出結果進行持久化語句與CLR類型的轉化。輸入參數類(Parameter object)經過SqlMap中設置的數據處理方式,並結合持久化數據處理方式(ADO.NET),從而產生輸出結果類(Result object)。對於.NET應用程序業務處理來說,實現了類的方法處理,從而實現了應用邏輯與數據持久化的隔離。
從上圖可以看出,輸入參數Parameter object和輸出結果Result object均支持集合類型、基本類型、值類型。其中間為核心的數據轉化過程。數據轉化過程是通過XML配置進行約束的。本文章為技術實踐文章,因此重點為IBatis相關配置文件的使用。
三、IBatis配置文件
1、SqlMap.config
IBatis基本運行環境的核心配置文件為SqlMap.config文件。它類似於應用程序的App.config和Web.config。IBatis的其他文件均是通過此配置文件加載到系統中的。基本的SqlMap.config如下圖所示:
SqlMap.config主要包括幾部分:Settings、providers、database、sqlMaps
Settings:主要進行IBatis全局基礎配置,它包括三個配置項
節點名 |
說明 |
默認值 |
useStatementNamespaces |
是否使用語句命名空間,這裏的命名空間指的是映射文件中sqlMap節點的namespace屬性。即如果該參數設為"true", 語句調用時需追加命名空間。 |
FALSE |
cacheModelsEnabled |
配置是否啟用IBatis的配置項緩存機制 |
TRUE |
validateSqlMap |
配置是否啟用SqlMapConfig.xsd schema驗證映射文件 |
FALSE |
其中useStatementNamespaces是在系統環境中可能需要應用的。當值為“true”調用語句時需要添加其配置文件頭中命名空間名稱。例如
當useStatementNamespaces="true",調用時則需要通過名稱“Complex.ComplexMap”,如果為false則通過名稱"ComplexMap"進行調用。
Providers:配置數據驅動提供類配置文件的路徑和文件名。
此配置中對應的文件中描述了多種數據驅動方式,通過配置可以保證IBatis支持市面上主流的數據(如Oracle\MsSql\MySql\sqlite\access等)。如需更換數據庫,需要將配置文件中相應啟動器的Enabled設置為“true”,並修改Database節中的配置即可。
Database:主要用來進行數據庫驅動器配置和數據庫連接字符串的配置。
provider的值應與providers配置文件中的name對應,並需要將providers配置文件中enabled設置為“true”。
dataSource的值為數據庫連接字符串。為了更好的匹配連接字符,減少修改連接字符串的復雜度,可采用properties進行預定義處理。
sqlMaps:可以在配置節中添加XML映射文件的位置,以指定項目內所包含的所有映射文件。引用xml文件有三種方式
參數 |
說明 |
resource |
指定數據驅動配置文件從項目的根目錄進行加載,如resource="providers.config" |
url |
指定數據驅動配置文件從文件的絕對路徑進行加載,如url="c:\IBatis\Resources\providers.config" -或者- url="file://c:\IBatis\Resources\providers.config" |
embedded |
指定數據驅動配置文件可以作為程序集的資源文件進行加載,如embedded="Resources.providers.config, MyApp.Data" |
配置文件中還有一些其他的配置方式(如properties、alias、typeHandlers),這裏就不一一介紹。
2、SqlMap.XML
SqlMap主要包括三部分,入參配置(Parameter)、返回結果配置(Result)、數據操作Sql配置(statements)。
parameter
用於配置入參格式,通過配置傳入到statements中,parameter可以用過parameterClass或parameterMap兩種方式傳入。
parameterClass可配置為應用程序類別名,將相應的類實例傳入到IBatis框架,通過其屬性名作為SqlMap語句匹配元素進行配置,從而生成相應的Sql語句。
parameterMap可以對parameterClass進行擴展,從而實現空值轉化、字段匹配等功能,通過配置的方式實現對空值、名稱匹配等的處理。
Result
Resul也包括兩種形式,resultClass和resultMap。resultClass配置可以將返回值映射為設定的類的實例,可以將查詢結果等映射到相應的類中。
resultMap對resultClass擴展,可以設置數據查詢字段與類數據字段的對應關系。
屬性 |
說明 |
parameterMap |
參數映射,需結合parameterMap節點對映射關系加以定義,對於存儲過程之外的statement而言,建議使用parameterClass作為參數配置方式,一方面避免了參數映射配置工作,另一方面其性能表現更加出色 |
parameterClass |
參數類。指定了參數類型的完整類名(包括命名空間),可以通過別名避免每次書寫冗長的類名 |
resultMap |
結果映射,需結合resultMap節點對映射關系加以定義 |
resultClass |
結果類。指定了結果類型的完整類名(包括命名空間),可以通過別名避免每次書寫冗長的類名 |
其中parameterMap和resultMap格式類似,主要包含如下屬性:
屬性 |
說明 |
property |
指定類中的一個屬性 |
column |
定義的參數名稱 |
direction |
用於聲明存儲過程的參數方向(input,output,inputoutput) |
dbType |
用於指定property映射到數據庫中的數據類型 |
type |
用於為參數的對象指定CLR類型 |
nullValue |
指定在property為何值時,將會在存儲數據時候,替換為null,這是經常會被用到的 |
size |
用於指定最大值 |
註:parameter和result都會涉及到類的屬性,按照C#語言特性,屬性等均是區分大小寫的,因此在進行XML配置時,需要特別註意。
Statements
IBatis進行類和Sql進行相互轉化的核心。他主要由id、parameter、result、動態Sql組成,前面初步介紹了id、parameter、result,以下終端介紹動態Sql語句。
為了更靈活的進行Sql語句匹配,IBatis進行了定義了多個運算符。
運算符 |
條件 |
說明 |
例程 |
isEqual |
二元條件 |
相等 |
<isEqual prepend="and" property="StartDate" compareValue="25/12/2004"> |
isNotEqual |
二元條件 |
不相等 |
<isNotEqual prepend="AND" property="year" compareValue="0"> |
isGreaterEqual |
二元條件 |
大於等於靜態值 |
<isGreaterEqual compareValue="3" > |
isGreaterThan |
二元條件 |
大於 |
<isGreaterThan prepend="AND" property="Id" compareValue="0" > |
isLessEqual |
二元條件 |
小於等於 |
<isLessEqual compareValue="3" > |
isLessThan |
二元條件 |
小於 |
<isLessThan compareValue="3" > |
isNotEmpty |
一元條件 |
是否不為 null 或不為空 |
<isNotEmpty prepend="and" property="LastName" > |
isEmpty |
一元條件 |
是否為 null或空 |
|
isNotNull |
一元條件 |
檢查屬性是否不為 null。 |
<isNotNull prepend="AND" property="FirstName"> |
isNotParameterPresent |
|
檢查是否不存在參數對象 |
<isNotParameterPresent prepend=”AND”> |
isNotPropertyAvailable |
一元條件 |
檢查是否不存在該屬性 |
|
isNull |
一元條件 |
檢查屬性是否為 null。 |
|
isParameterPresent |
|
檢查是否存在參數對象(不為 null)。 |
|
isPropertyAvailable |
一元條件 |
檢查是否存在該屬性 |
|
iterate |
|
|
|
運算符的使用主要是針對輸入參數的。
二元運算符
<isEqual property="name" compareValue="1" prepend="and"> a1= ‘abc‘ </isEqual>
輸入參數name屬性的值等於1時,將在sql中組合 a1= ‘abc‘,否則不進行Sql組合。
類似isNotEqual、isGreaterEqual、isGreaterThan、isLessEqual、isLessThan等均為類似的用法。
一元運算符
<isEmpty property="name" prepend="and"> a1= ‘abc‘ </isEqual>
輸入參數name屬性的值為空時,將在sql中組合 a1= ‘abc‘,否則不進行Sql組合。
數組運算符
將數組轉為化sql語句的一種方式,例如
<iterate property="Ids" open="(" close=")" conjunction="," =""> #Ids[]# </iterate>
將數組轉化為類似於“(1,2,3,4,5)”的Sql語句。
通過一系列的配置我們將程序的一個方法或一個對數據庫的操作轉化為一個SqlMap.Xml中的配置,方法入參轉化為parameter,方法出參轉化為result,而方法名轉化為id,從而實現了面向對象的業務方法轉化為數據庫操作。
IBatis除了以上語法要點,還包括一些其他語法例如extends、緩存等。完整的語法支持,保證了IBatis對絕大多數場景的支持。本文在很多知識點只是進行了簡單的說明,遠遠沒有展示IBatis的全貌。只有通過不斷的學習積累,並靈活應用才能發揮其強大的配置功能,才能更好的發揮IBatis的功能,實現真正的業務與數據的分離。
iBatis.net技術實踐