猿创征文|从mysql 到kingbase(人大金仓)
一、背景介绍
公司主要做toG 的项目,经常服务于各个地方政府。之前某省会城市下属区县项目,需要将已交付的项目中所使用到的各类中间件全部替换为国产,其中就包括了数据库的替换。项目中一直使用的是mysql数据库,后经商务调研及选型,决定替换为国产数据库 kingBase (人大金仓数据库),并由我负责所有应用的代码迁移工作。
我们的项目采用的是springCloud微服务体系,数据访问层用的是mybatisPlus, 微服务的个数比较多,我需要一个一个迁移并验证,这其实确实是一个比较繁琐且漫长的工作,并且由于只搭建了一套环境的数据库,我没法本地连接调试,每次都只能发包后通过观察错误日志的方式进行排查,给我的迁移工作增加了更大的困难。
二、适配过程
这里先强调一下,我的主要工作是把当前使用的mysql数据库,切换到人大金仓数据库上,这是一个迁移的过程,而不是说一个新项目从头开始就使用人大金仓,所以我所关注的主要就是mysql和人大金仓的兼容性上,把一些人大金仓无法成功的执行的mysql 中的语句改成能让他执行的语句。
而适配的第一步,其实主要是人大金仓的技术人员和我方的运维人员的工作。 首先由人大金仓的技术人员在我方指定的服务器上,帮助我们安装人大金仓的数据库,并且提供人大金仓(下面都使用kingbase替代)的数据库连接工具和相关的技术文档。并由我方运维人员根据他们提供的数据库迁移手册,将mysql上的数据迁移到kingbase中。完成迁移后,会给我一个kingbase数据库的连接相关信息(url,username,password等)和一份迁移文档。
接下来我就要根据文档进行应用上数据库迁移了,这里所说的迁移,其实就是做一个替换,将代码里的mysql连接替换成kingbase连接。替换步骤如下:
更换驱动
对方技术人员提供了一个驱动jar包,kingbase8-x.x.x.jar ,首先第一步我先将这个jar包上传到了公司私服上,然后用坐标的方式将其配置到了项目的pom文件中,同时注释掉里面的mysql驱动。
修改数据库连接配置信息
由于我们使用的是nacos配置中心,直接在nacos里进行修改:
spring:datasource:driver-class-name: com.kingbase8.Driver # 配置MySQL8的驱动程序类url: jdbc:kingbase8:/host:port/database?para1=val1...username: root # 数据库用户名password: root # 数据库连接密码
3. 重新启动服务,测试,解决报错。
上面这几步就是迁移的主要步骤了,如果运气比较好,完成上面的改动后,服务应该会正常启动,但是也有可能会出现一些问题,接下来就是要具体问题具体分析了,报的错误基本上都是sql不兼容的一些问题。然后就要根据具体的报错情况进行sql的适配。同时人大金仓的技术人员也会组建一个答疑的群,遇到一些报错可以发到答疑群中,他们也会有专业的技术人员进行解答。
三、常见问题解决
问题一: Error updateting database. Cause: com.kingbase8.util.KSQLException: ERROR: syntax error at or near "`"
这个问题是由于kingbase数据库不支持反引号造成的,有一些框架在生成一些增删改查语句的时候,可能习惯将字段名称使用反引号包裹起来,我们需要将反引号去掉或者改为双引号引号重新启动项目后解决。
类似于:
问题二: DATE_ADD函数不支持
sql中有使用DATE_ADD函数的地方报错,原因是默认的kingbase中是没有DATE_ADD函数的,需要自己创建(非系统函数,每个库都需要创建): 创建代码如下:
create or replace function date_add(v_date text , v_interval interval)returns text as $$declarev_rt text;beginselect to_char(v_date::timestamp(0) + v_interval,'yyyy-mm-dd hh24:mi:ss' ) into v_rt;if length(v_date) = 10 and v_rt like '% 00:00:00' thenselect substr(v_rt,0,10) into v_rt;end if;return v_rt;end;$$LANGUAGE plpgsql;
问题三: DATE_FORMAT 函数不支持
解决方案: 需要自己创建(非系统函数,每个库都需要创建),创建语句如下:
create or replace function date_format(para1 timestamp,para2 text) returns text
as $$
declare
form1 text;
begin
--form1=replace(para2,'%M','Month');
form1=replace(para2,'%W','Day');
--form1=replace(form1,'%D','DDth');
form1=replace(form1,'%Y','YYYY');
--form1=replace(form1,'%y','yy');
form1=replace(form1,'%a','Dy');
form1=replace(form1,'%d','DD');
form1=replace(form1,'%e','DD');
form1=replace(form1,'%m','MM');
form1=replace(form1,'%c','MM');
form1=replace(form1,'%b','Mon');
form1=replace(form1,'%j','DDD');
form1=replace(form1,'%H','HH24');
form1=replace(form1,'%k','HH24');
--form1=replace(form1,'%h','HH');
--form1=replace(form1,'%I','HH');
form1=replace(form1,'%l','HH');
form1=replace(form1,'%i','MI');
form1=replace(form1,'%r','HH:MI:SS');
form1=replace(form1,'%T','HH24:MI:SS');
--form1=replace(form1,'%S','SS');
form1=replace(form1,'%s','SS');
form1=replace(form1,'%%','%');
return to_char(para1,form1);
end;
$$ LANGUAGE plpgsql;
问题四: Cause: com.github.pagehelper.PageException: 无法自动获取数据库类型,请通过 helperDialect 参数指定!
解决方案: 在配置文件中手动指定:
pagehelper:helperDialect: postgresqlauto-runtime-dialect: false #默认参数,由于我的项目本地写死了true,我这里需要强制覆盖一下,如果配置成true,上面的配置不生效
问题五: ORDER BY isnull(kpi_seq), kpi_seq ASC ,create_time desc 报错
解决方案: kingbase不支持 isnull(字段名)的写法,需要改为一下写法:
ORDER BY kpi_seq isnull, kpi_seq ASC ,create_time desc
问题六: ERROR: CONNECT BY clause required in this query block
解决方案: 这个问题,主要是我在sql中使用了类似于name, level这样的关键字,kingbase中对于关键字的要求还是比较多的,有一些关键字是不允许我们在sql中使用的。解决方案有两种,一是把这些关键字的字段名修改一下。二是设置关键字的忽略。具体关键字有哪些,可以参考kingbase提供的文档,里面有详细参数。关键字忽略的方式,执行如下sql:
alter system set exclude_reserved_words = 'level';
select sys_reload_conf();
问题七: druid连接池在连接kingbase时会产生dbType not support, 或者 无法识别数据库类型的错误。
解决方案: 由于druild中一般会自动根据jdbc-url自动检查数据库的类型,但是它里面只有检查url中是否包含kingbase, 但是却不认识kingbase8,就会出现这个问题,我们需要自己设置driverClassName,同时druild的filter中要把wall去掉,因为kingbase不支持这个参数。
druidDataSource.setFilters("stat,slf4j");
druidDataSource.setDriverClassName("com.kingbase8.Driver")
问题八: com.kingbase8.util.KSQLException: Cannot convert the column of type TINYINT to requested type boolean.
解决方案: 这个问题主要是由于mysql中没有boolean类型,所以一般都使用tinyint来存储标志位,然后在实体中使用boolean类型来接收,类似mybatis或者mybatisPlus框架都会自动把tinyint类型转换为boolean类型。但是在kingbase里就不行了,解决方案: 这里只针对mybatisPlus,
首先实体类上的TableName注解中加入一个 autoResultMap = true
@TableName(value = “d_lc_res”, autoResultMap = true)
然后在boolean类型的字段注解上加上一个TypeHandler
@TableField(typeHandler = TinyIntToBooleanHandler.class, jdbcType= JdbcType.TINYINT)
private Boolean warningFlag;
TinyIntToBooleanHandler:
package com.xxx.global.config.mp;import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/**
* @className: TinyIntToBooleanHandler
* @description:
* @author liushuai
* @date 2022/9/19 3:21 PM
*/
@MappedTypes({Boolean.class})
@MappedJdbcTypes({JdbcType.TINYINT})
public class TinyIntToBooleanHandler extends BaseTypeHandler<Boolean> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {ps.setInt(i,Boolean.TRUE.equals(parameter) ? 1 : 0 );}@Overridepublic Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {int anInt = rs.getInt(columnName);return Integer.valueOf("1").equals(anInt);}@Overridepublic Boolean getNullableResult(ResultSet rs, int columnIndex) throws SQLException {int anInt = rs.getInt(columnIndex);return Integer.valueOf("1").equals(anInt);}@Overridepublic Boolean getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {int anInt = cs.getInt(columnIndex);return Integer.valueOf("1").equals(anInt);}
}
这样就可以了,这里要注意,这种方式只对mybatis已经封装好的方法有效,比如list, getOne,等,如果是我们自己写的sql, 还需要做进一步的处理:
对于自己写的sql, 我们需要使用resultMap来接收, 同时在定义resultMap的时候,给相应字段添加typeHandler属性:
<resultMap id="kpiDO" type="com.xxx.entity.KpiDO"><result column="warningFlag" property="warningFlag" typeHandler="com.cestc.global.config.mp.TinyIntToBooleanHandler" />// 省略其他字段</resultMap>
四、总结
上面就是最近一段时间在迁移国产数据库过程中的一些步骤和解决问题的方式,希望能够给大家带来帮助。整体来说迁移的过程还是比较痛苦的,上面只列出了常规应用的一些问题,还有一些使用动态数据源的应用,迁移起来的问题其实更大,像一些查询所有库,查询所有表,查询所有字段的sql写法和mysql都是完全不一样的。
虽然过程很艰辛,但是我想说的是,在大形势不断紧张的情况下,还是支持有更多企业、机构甚至个人,可以更多的支持国产软件的发展,有朝一日让我们的国产软件也能够站在世界的顶端,我们软件人不在遭受其他人的制裁与威胁。希望这一天早日到来,这也是全体中国软件人真正站起来的时候。
猿创征文|从mysql 到kingbase(人大金仓)相关推荐
- kingbase人大金仓常用sql命令(自用总结)
kingbase人大金仓常用sql命令(自用总结) 开发过程中使用到的 平时用mysql数据库,第一次用人大金仓数据库,有一些地方还是有区别,记录一下. –修改字段数据类型 –ALTER TABLE ...
- kingbase(人大金仓)数据库的常用知识点与简单巡检
KES服务的启停 查看服务是否已设为开机自启 systemctl list-dependencies |grep kingbase 除了使用systemctl和service还可以使用sys_ctl管 ...
- 猿创征文|MySQL入门到实战-基础篇
项目一 分析并设计学生管理数据库 主要目标是在了解用户软件操作需求的基础上,提炼.总结.归纳出对数据库的需求.主要内容,数据库的存储结构.表中数据及其依赖关系.设计方案的优化与规范.视图等其他数据库对 ...
- KINGBASE人大金仓数据库安装配置手册
1.上传安装包 安装包和license文件上传到/home/setup/kingbase目录 2.操作系统配置 关闭防火墙 中标麒麟: systemctl stop firewalld systemc ...
- IDEA连接kingbase人大金仓数据库
目录 在IDEA中配置数据库连接与DataGrip方法一样 kingbase8-8.2.0.jar 下载 URL temeplates 在IDEA中配置数据库连接与DataGrip方法一样 点击IDE ...
- 人大金仓助力广东省首届信创职业技能竞赛圆满完成
11月23日,广东省首届信创职业技能竞赛决赛成功举办.此次竞赛为2021年广东省职业技能大赛分散赛项之一,由广东省人力资源和社会保障厅主办,广东省公安厅网络警察总队提供业务指导,广东省网络空间安全协会 ...
- 信创升级 | 秒云与人大金仓完成兼容性互认证
近日,成都元来云志科技有限公司(简称"秒云")与北京人大金仓信息技术股份有限公司(简称"人大金仓")完成产品兼容互认证.本次兼容性互认证经秒云和人大金仓联合测试 ...
- 覆盖3700家机构!人大金仓联合卫宁健康助力广州市妇幼保健系统信创升级
目前,人大金仓联合卫宁健康共同承建的广州市妇幼保健系统信创适配改造项目已顺利上线,标志着人大金仓自主创新的技术.产品和解决方案再次实现行业信创应用场景落地,持续服务医疗行业数字化转型升级. 覆盖用户广 ...
- 创新界,聚势行 | 2022人大金仓“百城巡展”火热开启
6月29日,以"创新界·聚势行"为主题的2022人大金仓"百城巡展"系列活动火热开启.活动首站走进"蓉城"成都,由四川省信创联盟指导,传晟信 ...
最新文章
- NGUI_Depth
- jni和java之间字符串的转换
- shell实例第9讲:判断用户输入的是否为IP地址
- 【控制】多智能体系统总结。4.控制协议。
- 谷歌日语输入法电脑版_【Win安卓】谷歌地球电脑专业版和手机清爽版
- Firebug Command Line 的使用技巧
- plupload与springmvc分段上传视频
- 简单解决Python文件中文编码问题
- 计算机睡眠断网,win7睡眠不断网设置方法汇总
- java 多线程内存模型
- 2021年最推荐的十大进销存管理软件排名
- Yate for mac(标记和管理音频文件工具)
- Maven依赖冲突详解
- 万字拆解Gucci:率先迈向数字化的奢侈品,后来怎么样了?
- css好看的html径向渐变,CSS3径向渐变
- 汽车电子功能安全标准ISO26262解析(四)——FMEDA
- 傻瓜式部署教程2:docker搭建oracle11g数据库
- NOI 1789:算24
- JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。VIN车辆识别代号查询系统
- 组态王中PLC数据连接MySQL数据库教程