最近完成了一個(IBatis.Net+MVC)項目的數據庫+代碼遷移工作,可把我折騰得~~~
IBatis.Net是一個ORM框架,具體介紹可以問度娘。我之前沒用ORM框架使用經驗,所以這一路我不是走來的,而是爬出一個坑又掉入另外一個坑~~~
項目原來用的是Sqlserver2008,現在要轉到Oracle,所以我先完成數據遷移,然后是代碼遷移。
數據庫遷移
1、數據庫安裝與配置
略過。
2、表結構遷移
1)用PowerDesigner創建一個PhysicalDataModel,DBMS選擇Sqlserver2008;
2)選擇DataBase->Connect… ,連上Sqlserver數據庫;
3)選擇DataBase->Update Model from DataBase…,獲取Sqlserver數據庫的表結構和視圖,不獲取約束關系等(會影響數據導入);
4)選擇DataBase->Change Current DBMS…,選擇new DBMS為Oracle10gR2 ;
5)修改用戶,將原始dbo,修改成我們oracle的方案名(用戶名)。
90%的工作PowerDesigner已經為我完成了,剩下來就是修改字段類型和長度工作了。
修改字段類型和長度的部分,主要包括:
1)將轉換后的NUMBER和INTEGER類型都改成NUMBER(10)。sqlserver自增序列轉化后默認是NUMBER(6),這個肯定是不夠的;
2)將轉化后的FLOAT類型改為NUMBER(12,2);
3)將VARCHAR2長度都增加1倍,如sqlserver中的varchar(50),在oracle中就設置為varchar2(100)(注意:varchar(50)與varchar2(50)是有區別的)。
表字段類型和長度都修改完畢后,就是表的批量創建了。
3、數據導入
通過Sqlserver2008的DTS進行數據導入,數據導入失敗一般有以下幾種情況:
1)目標表中字段類型長度不夠;
2)表之間存在約束關系,如先在子表中導入數據,而主表又沒數據。
DTS導入完畢后,沒有返回到上一步功能,除非導入出錯。這個太不人性化了,太不厚道了~~~
4、主要工作已經完成,剩下就是創建序列和存儲過程的事情了。數據庫這部分基本搞定。在類型字段長度上,我返工了1次-_-有100多張表,坑啊~~~
項目的代碼遷移
1、IBatis的配置文件修改
providers.config文件中加入
<provider name="oracleClient1.0" description="Oracle, Microsoft provider V1.0.5000.0" enabled="true" assemblyName="System.Data.OracleClient, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" connectionClass="System.Data.OracleClient.OracleConnection" commandClass="System.Data.OracleClient.OracleCommand" parameterClass="System.Data.OracleClient.OracleParameter" parameterDbTypeClass="System.Data.OracleClient.OracleType" parameterDbTypeProperty="OracleType" dataAdapterClass="System.Data.OracleClient.OracleDataAdapter" commandBuilderClass="System.Data.OracleClient.OracleCommandBuilder" usePositionalParameters="false" useParameterPrefixInSql="true" useParameterPrefixInParameter="false" parameterPrefix=":" allowMARS="false" />
注意enable="true",並設置其余的provider節點 enable=“false”。
SqlMap.config文件中的連接字符串設置
<database> <provider name="oracleClient1.0" /> <dataSource name="ORCL" connectionString="Data Source=ORCL;user=用戶名;password=密碼"/> </database>
這個oracleClient1.0的連接字符串找了很久,開始一直以為是USER ID=用戶名。
2、Oracle客戶端的安裝
開始一直以為Oracle9i精簡版客戶端就可以搞定,結果老提示:Unable to open connection to "Oracle, Microsoft provider V1.0.5000.0"。於是下載並安裝了oracle10gR2的客戶端,還是不行。於是我在網上找了個ibatis.net+oracle的winform版demo,測試正常,可以確認不是配置文件和連接字符串的問題了。可將代碼移植到web項目上就不行了,即使部署到IIS上並模擬32位運行(開發機是win7x64系統)也是出錯。32位模式運行的時候會提示要求更高的客戶端版本。難道是新安裝的客戶端的時候在環境變量中新增加的Path沒生效?於是抱抱試試看的心態,重啟了電腦,終於老天是眷顧程序猿的~~~搞定。
3、SQL語句代碼修改
1)dbType=Int 都換成dbType=Number
2)遇到<等會破壞XML文件格式的符號,將其放在<![CDATA[……]]>中
3)Oracle的自增序列
<insert id="Insert" parameterClass="Account"> <selectKey property="UserID" resultClass="int" type="pre"> SELECT SEQ_ACCOUNT_ID.NEXTVAL AS VALUE FROM DUAL </selectKey> INSERT INTO Account ( USERID ,Name , AccountNo , MobileNo , Password ) VALUES ( #UserID# ,#Name,dbType=VarChar# , #AccountNo,dbType=VarChar# , #MobileNo,dbType=VarChar# , #Password,dbType=VarChar# ) </insert>
注意:自增序列的值,上面代碼段中我用的是UserId,這個要與XML中向對應,我之前都用了ID,結果踩到坑了。
<resultMaps> <resultMap id="FullResultMap" class="Account"> <result property="UserID" column="UserID" dbType="Int"/>
4)select top的實現
<select id="XXXXXXXX" parameterClass="Hashtable" resultMap="NonLobResultMap"> SELECT * FROM ( SELECT rownum as rn ,ID , Title FROM Article WHERE (OwnerID = #OwnerID,dbType=Number#) ORDER BY CreateTime DESC ) tb <![CDATA[ where rn <= $ReturnCount$ ]]> </select>
5)分頁的實現
<select id="Search" parameterClass="Hashtable" resultMap="FullResultMap"> SELECT * From( SELECT rownum as RowNumber,Article.* FROM Article <include refid="SearchWhere"></include> <![CDATA[ order by ID DESC ) tb where RowNumber >=( ($PageIndex$ - 1) * $PageSize$ + 1) and RowNumber<=( $PageIndex$ * $PageSize$) ]]> </select>
6)like模糊查詢
<select id="XXX" parameterClass="Citys" resultMap="FullResultMap" extends="FindAll"> where (Namelike '%'|| #Name,dbType=VarChar#||'%') </select>
7)存儲過程返回游標
<parameterMaps> <!-- 存儲過程參數 --> <parameterMap id="parm_sp_XXXXXX" class="Hashtable"> <parameter property="AAAAAA" column="IN_AAAAAA" direction="Input" /> <parameter property="BBBBBB" column="IN_BBBBBB" direction="Input" /> <parameter property="Result" column="OUT_REF_CUR" dbType="Cursor" direction="Output" /> </parameterMap> </parameterMaps> <statements> <!-- 存儲過程 --> <procedure id="GetXXXXXXXXXXXX" parameterMap="parm_sp_XXXXXX" resultMap="YYYYYYYYYYYYY"> proc_存儲過程名稱 </procedure>
</statements>
8)Oracle對字段取別名可以用as,但是對表就不能用as
9)select * ,然后增加其他字段,就需要在*前面加上表名,如t.*
10)然后把一些SQL命令改成Oracle的命令
11)SQL語句的腳本文件中,建議將存儲過程、參數、序列等都用大寫表示。
總結
初次接觸Ibatis.Net,通過代碼生成器為我們完成大部分工程,開發上確實很方便,在后期做數據庫遷移的時候,工作量比傳統的工廠模式或IOC少很多,修改的時候直接在對應的XML上修改,非常直觀方便。