背景
之前因项目客户要求,需要适配国产数据库-达梦(这里适配的是达梦大型通用数据库管理系统,简称DM7),对代码中的sql 改造,同时因为项目中的数据库的建表脚本、字典等都是使用 liquibase 管理的,所以也需要扩展 liquibase 。
在我们的使用中,达梦因为开启了 Oracle 的兼容模式,所以 sql 基本无需改造,但 liquibase 本身不支持达梦数据库,仍需要写代码适配。
注:如果需要搭建本地环境测试或者是体验,可以直接使用 docker 搭建,快速验证下效果,这里使用的是镜像是 flobit/dm7
,启动命令为 docker run -d --name dm7 -p5236:5236 flobit/dm7
,账号密码为 sysdba/strongP@ssW0rd
。
适配实现
感谢 liquibase 良好的扩展机制,我们一般只需要扩展两点即可:
- AbstractJdbcDatabase 声明适配的数据库的元数据、连接的创建等
- LiquibaseDataType 声明 java 类型 和数据库字段类型的转换
liquibase版本为 3.5.3.
达梦数据库的依赖如下
<dependency>
<groupId>com.dameng</groupId>
<artifactId>Dm7JdbcDriver18</artifactId>
<version>7.6.0.165</version>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmDialect-for-hibernate2.0</artifactId>
<version>8.1.1.49</version>
</dependency>
实现 AbstractJdbcDatabase
笔者一开始为了省事,直接继承 OracleDatabase
然后再复写其中方法,这样会导致的 liquibase 自身的表无法创建成功,也尝试继承 MySqlDatabase
,这样则是导致 liquibase 重复创建 DATABASECHANGELOG
从而失败。(这里挺有意思,后面再展开说说)
正确的做法,应该是直接复制 OracleDatabase 的代码,声明为新类,然后修改其中相关的方法。
实现如下
public class DaMengDatabase extends AbstractJdbcDatabase {
public DaMengDatabase() {
super.unquotedObjectsAreUppercased=true;
super.setCurrentDateTimeFunction("SYSTIMESTAMP");
// Setting list of Oracle's native functions
dateFunctions.add(new DatabaseFunction("SYSDATE"));
dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP"));
dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP"));
super.sequenceNextValueFunction = "%s.nextval";
super.sequenceCurrentValueFunction = "%s.currval";
}
@Override
public String getShortName() {
return "dm";