事件发生的背景同动弹同步,我接到了一个把个人项目从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 ]]>