事件發生的背景同動彈同步,我接到了一個把個人項目從mysql遷移到oracle數據庫的噩耗。原本覺得這事件麻煩的事兒,可是實際狀況比我想的麻煩的多。mysql
順便總結一下我換庫遇到的種種問題:sql
一、mysql和oracle的分頁方式不同,涉及到分頁的地方要注意數據庫
二、oracle的自增加要寫函數本身實現,並不能像MySql那樣去直接用自增加屬性mybatis
三、mysql中的不少經常使用字段如 id,name,sort,description...在Oracle中被強制爲關鍵字佔用,因此你在mysql中導出的建表語句並不適用oracle
四、mysql和oracle中字段類型不通用,這也致使了你mysql中導出的建表語句並不適用app
五、日期字段的處理,這個我就很少說了函數
六、空字符的處理,MYSQL的非空字段也有空的內容,ORACLE裏定義了非空字段就不允許有空的內容。按MYSQL的NOT NULL來定義ORACLE表結構,導數據的時候會產生錯誤。所以導數據時要對空字符進行判斷,若是爲NULL或空字符,須要把它改爲一個空格的字符串。測試
這些都是次要的,下面咱們來切入主題:spa
第一步,實現oracle的自增加,首先你要有一個序列code
CREATE SEQUENCE portal_sequence --序列名 INCREMENT BY 1 -- 每次加幾個 START WITH 250 -- 從1開始計數 NOMAXVALUE -- 不設置最大值 NOCYCLE; -- 一直累加,不循環 ;
定義好sequence後,你就能夠用currVal,nextVal取得值。
CurrVal:返回 sequence的當前值
NextVal:增長sequence的值,而後返回 增長後sequence值
而後在進行插入操做時就能夠:
insert into p_sys_rolemenu (rm_id,role_id, menu_id,creator, create_time,update_time,updator, is_deleted) select get_seq('portal_sequence.nextval') , 2,113,053023,sysdate,sysdate,053023,0 from dual
第二步,也是咱們要處理的問題了:我在mybatis中涉及了批量的插入使用了foreach,而後我把當時在mysql底下的xml問題貼出來。
<insert id="insert" parameterType="com.aneop.sys.userfunc.entity.RoleMenu" > insert into t_sys_rolemenu (role_id, menu_id,creator, create_time,update_time,updator, is_deleted) <foreach collection="list" separator="UNION ALL" item="item"> select #{item.roleId},#{item.menuId},#{item.creator},NOW(),NOW(),#{item.creator},0 </foreach> </insert>
而後這個確定是不行的啊,沒有rm_id的自增加主鍵。因此我就稍微修改了下:
理所應當的把portal_sequence.nextval加上去了,而後測試了一下,居然成功了,而後我繼續測了一下才發現,在list.size()<=1的時候是沒問題的,一旦list裏面有兩條/兩條以上的記錄時就涉及到了union all,而後就又不成功了。
<insert id="insert" parameterType="com.ane56.sys.userfunc.entity.RoleMenu" > insert into p_sys_rolemenu (rm_id,role_id, menu_id,creator, create_time,update_time,updator, is_deleted) <foreach collection="list" separator="UNION ALL" item="item"> select portal_sequence.nextval, #{item.roleId},#{item.menuId},#{item.creator},sysdate,sysdate,#{item.creator},0 from dual </foreach> </insert>
通過網上一翻查找,最後定義到了問題,要先建立函數才能夠,建立函數get_seq()
create or replace function get_seq (p_in_sqname in varchar2) return number is l_res number ; begin execute immediate 'select '|| p_in_sqname|| '.nextval from dual' into l_res ; return l_res ; end ;
而後我把我xml裏面的foreach修改成以下狀況,在調用序列的時候經過個人get_seq()函數來調用:
<insert id="insert" parameterType="com.ane56.sys.userfunc.entity.RoleMenu" > insert into p_sys_rolemenu (rm_id,role_id, menu_id,creator, create_time,update_time,updator, is_deleted) <foreach collection="list" separator="UNION ALL" item="item"> select get_seq('portal_sequence.nextval'), #{item.roleId},#{item.menuId},#{item.creator},sysdate,sysdate,#{item.creator},0 from dual </foreach> </insert>
問題完美解決,這個bug浪費時間超過兩個,在此記錄下。
附帶貼上mybatis中的轉移字符以下:
< | > | 大於號 |
> | < | 小於號 |
& | & | 和 |
' | ' | 單引號 |
" | " | 雙引號 |
由於這個是xml格式的,因此不容許出現相似「>」這樣的字符,可是均可以使用<![CDATA[ ]]>符號進行說明,將此類符號不進行解析
你的能夠寫成這個:
mapper文件示例代碼
<![CDATA[ where rowno <=60 and rowno >=40 ]]>