记一次基于mybatis的Springboot项目数据库从Mysql迁移至Oracle的全过程(超详细)
前言
自己做了一个后端使用springboot,前端使用vue的前后端分离的知识图谱系统,图数据库用Neo4j,关系数据库用的mysql,在项目上线前一周,甲方爸爸要求关系数据库要使用Oracle11g,无情,加班几天终于完成了Mysql8.5迁移至Oracle11g的全过程,技术点不难,但是太麻烦了,因此在此记录一下,希望能帮到一些小伙伴,初次在CSDN上写博客,希望大家体谅一下,不喜勿喷!
(一)MySQL数据库中的表数据迁移到Oracle数据库
具体的操作流程和方法见链接:
从 MySQL 迁移数据到 Oracle 中的全过程
在这里主要补充一些细节:
Navicat安装**
详情见链接:
Navicat安装**教程
使用上述方法将Mysql数据迁移至Oracle数据库之后,有一些要注意的地方,在这里,我只对自己修改的地方进行一下记录:
- 表名及其中的字段名全部变为大写
- int类型的字段迁移至Oracle后变为Number
- date类型的字段没有变化
- varchar和text类型的字段统一改为varchar2
- mysql自定义的存储过程需要重写
关于序列自增的问题,上述教程已经说的较为详细,在这里将新增序列的代码贴上作为补充:
-- auto-generated definition
create sequence KGDEPARTMENT
start with 1000
increment by 1
minvalue 1000
maxvalue 99999999
nocycle
nocache
tinyint字段需要重新定义
因为在mysql中,tinyint值为0时,默认为false,值为1时,返回的是true。但是在oracle中,并没有这类字段,很多时候我们用到此字段作为是否有效的标识,因此,包括使用SpringSecurity的过程中,登录用户是否有效也需要enabled这个字段。
因此之前写的用此字段判断true和false的代码逻辑需要重写,改为使用int类型的数字0和1来判断。
登录用户类处理enabled字段的方法:
@Override
public boolean isEnabled() {
return enabled==1?true:false;
}
后端其他常用类处理enabled字段的方法:
private Integer enabled;
public Integer getEnabled() {
return enabled;
}
public void setEnabled(Integer enabled) {
this.enabled = enabled;
}
前端使用了Element组件中Switch滑块,因此要对返回的Enabled子段进行处理
是否启用:
<el-table-column
label="是否启用">
<template slot-scope="scope">
<el-tag size="small" type="success" v-if="scope.row.enabled==1">已启用</el-tag>
<el-tag size="small" type="danger" v-else>未启用</el-tag>
</template>
</el-table-column>
showEditView(index, data) {
//console.log(data)
if( data.enabled==1){
data.enabled=true;
}else {
data.enabled=false;
}
Object.assign(this.updateDevelopPhase, data);
this.dialogVisible = true;
// console.log(this.updateDevelopPhase)
},
doUpdate() {
if(this.updateDevelopPhase.enabled==true){
this.updateDevelopPhase.enabled=1;
}else {
this.updateDevelopPhase.enabled=0;
}
this.putRequest("/system/dic/developPhase/", this.updateDevelopPhase).then(resp => {
if (resp) {
this.initDevelopPhases();
this.updateDevelopPhase.name = '';
this.dialogVisible = false;
}
})
},
(二)使用mybatis逆向工具生成Oracle对应表的实体类以及对应的映射方法
在这里我使用的mybatis逆向生成工具已上传至百度网盘,内附使用说明,如何使用大家下载阅读使用说明即可:
网盘链接:https://pan.baidu.com/s/1Kn7LMoyQoyHjDYBq9fuYMQ
提取码:9jqi
生成对应的类以及mapper文件后,并不能立即在项目中使用,有些命名规则或者细节上需要修改:
1 生成的Model实体类中字段名以及.xml文件中property的属性名统统改为驼峰法则命名的形式,此字段名为返回到前端数据的数据属性。
2 由于mysql有主键自增的方式,而oracle只能通过序列自增的方式,因此插入方法中,要引入序列,具体实现看代码:
<insert id="insert" parameterType="org.javaboy.vhr.model.KgReason1" >
insert into KG_REASON1 (ID, NAME, CREATEDATE,
ENABLED)
values (KGREASON1.nextval, #{name,jdbcType=VARCHAR}, #{createDate,jdbcType=DATE},
#{enabled,jdbcType=DECIMAL})
</insert>
3 批量插入方法也有很大不同,具体看Demo:
java方法:
Integer addQualityResetProblems(@Param("list") List<KgQualityResetProblem> list);
mysql实现:
<insert id="addQualityResetProblems" useGeneratedKeys="false"
parameterType="org.javaboy.vhr.model.KgQualityResetProblem">
INSERT INTO KG_QUALITYRESETPROBLEM(ID, ...)
SELECT KGQUALITYRESETPROBLEM.nextval,s.* FROM
(
<foreach collection="list" item="qualityResetProblem" separator="UNION ALL">
SELECT #{qualityResetProblem.fSecret,jdbcType=VARCHAR},
...}
FROM dual
</foreach>
) s
</insert>
4 分页功能也有很大不同,具体看Demo:
java Service层方法:
public RespPageBean getQualityResetProblemByPage(Integer page, Integer size) {
if (page != null && size != null) {
page = (page - 1) * size;
}
List<KgQualityResetProblem> data = kgQualityResetProblemMapper.getQualityResetProblemByPage(page, size);
Long total = kgQualityResetProblemMapper.getTotal();
RespPageBean bean = new RespPageBean();
bean.setData(data);
bean.setTotal(total);
return bean;
}
Dao层:
List<KgQualityResetProblem> getQualityResetProblemByPage(@Param("page") Integer page, @Param("size") Integer size);
SQL语句:
<select id="getQualityResetProblemByPage" resultMap="AllQualityResetProblemInfo">
SELECT *
from
(select A.*,ROWNUM RN from(
SELECT qua.* ,
D1."NAME" AS DESIGNDEPTNAME ,D1."ID" as DESIGNDEPTID ,
D2."NAME" AS PRODUCEDEPTNAME , D2."ID" as PRODUCEDEPTID,
D3."NAME" AS DUTYDEPTNAME ,D3."ID" as DUTYDEPTID,
D4."NAME" AS OUTDEPTNAME ,D4."ID" as OUTDEPTID,
KG_REASON1."NAME" AS CAUSECLASS1NAME ,KG_REASON1."ID" as CAUSECLASS1ID ,
KG_REASON2."NAME" AS CAUSECLASS2NAME , KG_REASON2."ID" as CAUSECLASS2ID,
KG_WORKPHASE."NAME" AS WNAME ,KG_WORKPHASE."ID" as WID,
KG_PRODUCTLEVEL."NAME" AS PNAME ,KG_PRODUCTLEVEL."ID" as PID,
KG_DEVELOPPHASE."NAME" AS DNAME ,KG_DEVELOPPHASE."ID" as DID
from KG_QUALITYRESETPROBLEM qua
left join KG_DEPARTMENT D1 on qua."FPRODUCTDESIGNDEPTID"=D1."ID"
left join KG_DEPARTMENT D2 on qua."FPRODUCTPRODUCEDEPTID"=D2."ID"
left join KG_DEPARTMENT D3 on qua."FDUTYDEPTID"=D3."ID"
left join KG_DEPARTMENT D4 on qua."FOUTDEPTNAMEID"=D4."ID"
left join KG_REASON1 on qua."FCAUSATIONCLASS1ID"=KG_REASON1."ID"
left join KG_REASON2 on qua."FCAUSATIONCLASS2ID"=KG_REASON2."ID"
left join KG_WORKPHASE on qua."FWORKPHASE1ID"=KG_WORKPHASE."ID"
left join KG_PRODUCTLEVEL on qua."FPRODUCTLEVELID"=KG_PRODUCTLEVEL."ID"
left join KG_DEVELOPPHASE on qua."FMODELDEVELOPPHASEID"=KG_DEVELOPPHASE."ID"
order by qua.ID DESC
)A
where ROWNUM <=(#{page}+#{size})
)
where RN > #{page}
</select>
在这里,补充一些mysql和oracle SQL语句踩得坑:
- mysql语句单引号,oracle都要转换为双引号
- mysql语句可以在句末加;号,oracle不能加;号
- mysql数据库表以及对应字段可以*大小写,oracle表和字段都要大写
- mysql中表类型为text的字段到oracle后为CLOB,但在这里我要改为varchar2字段类型,因此使用在oracle表中要先删除该字段,再重新添加该字段。
(三)Springboot项目中引入Oracle
propertie文件配置:
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
#spring.datasource.url=jdbc:oracle:thin:@localhost:1521:QQJG
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:QQJG
spring.datasource.username=
spring.datasource.password=
maven项目引入配置:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.1.0</version>
</dependency>
下载oracle相关依赖:
参考该链接:
下载oracle相关依赖
上一篇: 记一次sparksql读取oracle数据优化过程
下一篇: 重置git提交作者信息