liquibase扩展支持达梦数据库

近期项目中需要支持国产数据库,需要liquibase底层支持达梦数据库,记录下操作的详细步骤以便分享。
1.liquibase支持的数据库很多如MySQL, PostgreSQL, Oracle, Sql Server, DB2。但是达梦数据库并不支持,所以需要新建DMDatabase类来适配达梦数据库。达梦语法和Oracle很像所以只需要复制liquibase-core下的Oracle Database做些修改就可了。以下为需要修改的地方

public class DMDatabase extends AbstractJdbcDatabase {
public static final String PRODUCT_NAME = "DM DBMS";@Overridepublic String getShortName() {//noinspection HardCodedStringLiteralreturn "dm";}@Overrideprotected String getDefaultDatabaseProductName() {//noinspection HardCodedStringLiteralreturn PRODUCT_NAME;}@Overridepublic Integer getDefaultPort() {return 5236;}@Overridepublic String getDefaultDriver(String url) {//noinspection HardCodedStringLiteralif (url.startsWith("jdbc:dm")) {return "dm.jdbc.driver.DmDriver";}return null;}
}

2.达梦不支持booelan类型需要转为int,所以需要修改Boolean类,修改地方为://支持达梦自增列

@DataTypeInfo(name = "boolean", aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT)
public class BooleanType extends LiquibaseDataType {@Overridepublic DatabaseDataType toDatabaseDataType(Database database) {String originalDefinition = StringUtils.trimToEmpty(getRawDefinition());if ((database instanceof AbstractDb2Database) || (database instanceof FirebirdDatabase)) {return new DatabaseDataType("SMALLINT");} else if (database instanceof MSSQLDatabase) {return new DatabaseDataType(database.escapeDataTypeName("bit"));} else if (database instanceof MySQLDatabase) {if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {return new DatabaseDataType("BIT", getParameters());}return new DatabaseDataType("BIT", 1);} else if (database instanceof OracleDatabase) {return new DatabaseDataType("NUMBER", 1);} else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase)) {return new DatabaseDataType("BIT");} else if (database instanceof DerbyDatabase) {if (((DerbyDatabase) database).supportsBooleanDataType()) {return new DatabaseDataType("BOOLEAN");} else {return new DatabaseDataType("SMALLINT");}} else if (database instanceof HsqlDatabase) {return new DatabaseDataType("BOOLEAN");} else if (database instanceof PostgresDatabase) {if (originalDefinition.toLowerCase(Locale.US).startsWith("bit")) {return new DatabaseDataType("BIT", getParameters());}}//转intelse if (database instanceof DMDatabase){return new DatabaseDataType("INT");}return super.toDatabaseDataType(database);}protected boolean isNumericBoolean(Database database) {if (database instanceof DerbyDatabase) {return !((DerbyDatabase) database).supportsBooleanDataType();}return (database instanceof AbstractDb2Database) || (database instanceof FirebirdDatabase) || (database instanceofMSSQLDatabase) || (database instanceof MySQLDatabase) || (database instanceof OracleDatabase) ||(database instanceof SQLiteDatabase) || (database instanceof SybaseASADatabase) || (database instanceofSybaseDatabase) || (database instanceof DMDatabase);}
}
  1. 达梦的自增列语法与其他不同需要修改CreateTableGenerator类
    @Overridepublic Sql[] generateSql(CreateTableStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) {List<Sql> additionalSql = new ArrayList<>();StringBuffer buffer = new StringBuffer();buffer.append("CREATE TABLE ").append(database.escapeTableName(statement.getCatalogName(),statement.getSchemaName(), statement.getTableName())).append(" ");buffer.append("(");boolean isSinglePrimaryKeyColumn = (statement.getPrimaryKeyConstraint() != null) && (statement.getPrimaryKeyConstraint().getColumns().size() == 1);boolean isPrimaryKeyAutoIncrement = false;Iterator<String> columnIterator = statement.getColumns().iterator();BigInteger mysqlTableOptionStartWith = null;/* We have reached the point after "CREATE TABLE ... (" and will now iterate through the column list. */while (columnIterator.hasNext()) {String column = columnIterator.next();DatabaseDataType columnType = statement.getColumnTypes().get(column).toDatabaseDataType(database);buffer.append(database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), column, true));buffer.append(" ").append(columnType);AutoIncrementConstraint autoIncrementConstraint = null;for (AutoIncrementConstraint currentAutoIncrementConstraint : statement.getAutoIncrementConstraints()) {if (column.equals(currentAutoIncrementConstraint.getColumnName())) {autoIncrementConstraint = currentAutoIncrementConstraint;break;}}boolean isAutoIncrementColumn = autoIncrementConstraint != null;boolean isPrimaryKeyColumn = (statement.getPrimaryKeyConstraint() != null) && statement.getPrimaryKeyConstraint().getColumns().contains(column);isPrimaryKeyAutoIncrement = isPrimaryKeyAutoIncrement || (isPrimaryKeyColumn && isAutoIncrementColumn);if ((database instanceof SQLiteDatabase) &&isSinglePrimaryKeyColumn &&isPrimaryKeyColumn &&isAutoIncrementColumn) {String pkName = StringUtils.trimToNull(statement.getPrimaryKeyConstraint().getConstraintName());if (pkName == null) {pkName = database.generatePrimaryKeyName(statement.getTableName());}if (pkName != null) {buffer.append(" CONSTRAINT ");buffer.append(database.escapeConstraintName(pkName));}buffer.append(" PRIMARY KEY");}// for the serial data type in postgres, there should be no default valueif (!columnType.isAutoIncrement() && (statement.getDefaultValue(column) != null)) {Object defaultValue = statement.getDefaultValue(column);if (database instanceof MSSQLDatabase) {String constraintName = statement.getDefaultValueConstraintName(column);if (constraintName == null) {constraintName = ((MSSQLDatabase) database).generateDefaultConstraintName(statement.getTableName(), column);}buffer.append(" CONSTRAINT ").append(database.escapeObjectName(constraintName, ForeignKey.class));}if ((database instanceof OracleDatabase) && statement.getDefaultValue(column).toString().startsWith("GENERATED ALWAYS ")) {buffer.append(" ");} else if (database instanceof Db2zDatabase && statement.getDefaultValue(column).toString().contains("CURRENT TIMESTAMP")|| statement.getDefaultValue(column).toString().contains("IDENTITY GENERATED BY DEFAULT")) {buffer.append(" ");} else {buffer.append(" DEFAULT ");}if (defaultValue instanceof DatabaseFunction) {buffer.append(database.generateDatabaseFunctionValue((DatabaseFunction) defaultValue));} else if (database instanceof Db2zDatabase) {if (statement.getDefaultValue(column).toString().contains("CURRENT TIMESTAMP")) {buffer.append("");}if (statement.getDefaultValue(column).toString().contains("IDENTITY GENERATED BY DEFAULT")) {buffer.append("GENERATED BY DEFAULT AS IDENTITY");}if (statement.getDefaultValue(column).toString().contains("CURRENT USER")) {buffer.append("SESSION_USER ");}if (statement.getDefaultValue(column).toString().contains("CURRENT SQLID")) {buffer.append("CURRENT SQLID ");}} else {buffer.append(statement.getColumnTypes().get(column).objectToSql(defaultValue, database));}}if (isAutoIncrementColumn) {// TODO: check if database supports auto increment on non primary key columnif (database.supportsAutoIncrement()) {String autoIncrementClause = database.getAutoIncrementClause(autoIncrementConstraint.getStartWith(), autoIncrementConstraint.getIncrementBy());if (!"".equals(autoIncrementClause)) {buffer.append(" ").append(autoIncrementClause);}if( autoIncrementConstraint.getStartWith() != null ){if (database instanceof PostgresDatabase) {String sequenceName = statement.getTableName()+"_"+column+"_seq";additionalSql.add(new UnparsedSql("alter sequence "+database.escapeSequenceName(statement.getCatalogName(), statement.getSchemaName(), sequenceName)+" start with "+autoIncrementConstraint.getStartWith(), new Sequence().setName(sequenceName).setSchema(statement.getCatalogName(), statement.getSchemaName())));}else if(database instanceof MySQLDatabase){mysqlTableOptionStartWith = autoIncrementConstraint.getStartWith();}}}//支持达梦自增列else if(isAutoIncrementColumn && database instanceof DMDatabase){buffer.append(" identity(1,1)");}else {LogService.getLog(getClass()).warning(LogType.LOG, database.getShortName()+" does not support autoincrement columns as requested for "+(database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName())));}}// Do we have a NOT NULL constraint for this column?if (statement.getNotNullColumns().get(column) != null) {if (! database.supportsNotNullConstraintNames()) {buffer.append(" NOT NULL");} else {/* Determine if the NOT NULL constraint has a name. */NotNullConstraint nnConstraintForThisColumn = statement.getNotNullColumns().get(column);String nncName = StringUtils.trimToNull(nnConstraintForThisColumn.getName());if (nncName == null) {buffer.append(" NOT NULL");} else {buffer.append(" CONSTRAINT ");buffer.append(database.escapeConstraintName(nncName));buffer.append(" NOT NULL");} // do we have a NN constraint name?} // does the DB support constraint names?} else {if ((database instanceof SybaseDatabase) || (database instanceof SybaseASADatabase) || (databaseinstanceof MySQLDatabase) || ((database instanceof MSSQLDatabase) && columnType.toString().toLowerCase().contains("timestamp"))) {buffer.append(" NULL");} // Do we need to specify NULL explicitly?} // Do we have a NOT NULL constraint for this column?if ((database instanceof MySQLDatabase) && (statement.getColumnRemarks(column) != null)) {buffer.append(" COMMENT '" + database.escapeStringForDatabase(statement.getColumnRemarks(column)) + "'");}if (columnIterator.hasNext()) {buffer.append(", ");}}buffer.append(",");if (!( (database instanceof SQLiteDatabase) &&isSinglePrimaryKeyColumn &&isPrimaryKeyAutoIncrement) ) {if ((statement.getPrimaryKeyConstraint() != null) && !statement.getPrimaryKeyConstraint().getColumns().isEmpty()) {if (database.supportsPrimaryKeyNames()) {String pkName = StringUtils.trimToNull(statement.getPrimaryKeyConstraint().getConstraintName());if (pkName == null) {// TODO ORA-00972: identifier is too long// If tableName lenght is more then 28 symbols// then generated pkName will be incorrectpkName = database.generatePrimaryKeyName(statement.getTableName());}if (pkName != null) {buffer.append(" CONSTRAINT ");buffer.append(database.escapeConstraintName(pkName));}}buffer.append(" PRIMARY KEY (");buffer.append(database.escapeColumnNameList(StringUtils.join(statement.getPrimaryKeyConstraint().getColumns(), ", ")));buffer.append(")");// Setting up table space for PK's index if it existif (((database instanceof OracleDatabase) || (database instanceof PostgresDatabase)) && (statement.getPrimaryKeyConstraint().getTablespace() != null)) {buffer.append(" USING INDEX TABLESPACE ");buffer.append(statement.getPrimaryKeyConstraint().getTablespace());}buffer.append(",");}}for (ForeignKeyConstraint fkConstraint : statement.getForeignKeyConstraints()) {if (!(database instanceof InformixDatabase)) {buffer.append(" CONSTRAINT ");buffer.append(database.escapeConstraintName(fkConstraint.getForeignKeyName()));}String referencesString = fkConstraint.getReferences();buffer.append(" FOREIGN KEY (").append(database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), fkConstraint.getColumn())).append(") REFERENCES ");if (referencesString != null) {if (!referencesString.contains(".") && (database.getDefaultSchemaName() != null) && database.getOutputDefaultSchema()) {referencesString = database.escapeObjectName(database.getDefaultSchemaName(), Schema.class) +"."+referencesString;}buffer.append(referencesString);} else {buffer.append(database.escapeObjectName(fkConstraint.getReferencedTableCatalogName(), fkConstraint.getReferencedTableSchemaName(), fkConstraint.getReferencedTableName(), Table.class)).append("(").append(database.escapeColumnNameList(fkConstraint.getReferencedColumnNames())).append(")");}if (fkConstraint.isDeleteCascade()) {buffer.append(" ON DELETE CASCADE");}if ((database instanceof InformixDatabase)) {buffer.append(" CONSTRAINT ");buffer.append(database.escapeConstraintName(fkConstraint.getForeignKeyName()));}if (fkConstraint.isInitiallyDeferred()) {buffer.append(" INITIALLY DEFERRED");}if (fkConstraint.isDeferrable()) {buffer.append(" DEFERRABLE");}buffer.append(",");}for (UniqueConstraint uniqueConstraint : statement.getUniqueConstraints()) {if (uniqueConstraint.getConstraintName() != null) {buffer.append(" CONSTRAINT ");buffer.append(database.escapeConstraintName(uniqueConstraint.getConstraintName()));}buffer.append(" UNIQUE (");buffer.append(database.escapeColumnNameList(StringUtils.join(uniqueConstraint.getColumns(), ", ")));buffer.append(")");buffer.append(",");}/** Here, the list of columns and constraints in the form* ( column1, ..., columnN, constraint1, ..., constraintN,* ends. We cannot leave an expression like ", )", so we remove the last comma.*/String sql = buffer.toString().replaceFirst(",\\s*$", "")+")";if ((database instanceof MySQLDatabase) && (mysqlTableOptionStartWith != null)){LogService.getLog(getClass()).info(LogType.LOG, "[MySQL] Using last startWith statement ("+mysqlTableOptionStartWith.toString()+") as table option.");sql += " "+((MySQLDatabase)database).getTableOptionAutoIncrementStartWithClause(mysqlTableOptionStartWith);}if ((statement.getTablespace() != null) && database.supportsTablespaces()) {if ((database instanceof MSSQLDatabase) || (database instanceof SybaseASADatabase)) {sql += " ON " + statement.getTablespace();} else if ((database instanceof AbstractDb2Database) || (database instanceof InformixDatabase)) {sql += " IN " + statement.getTablespace();} else {sql += " TABLESPACE " + statement.getTablespace();}}if((database instanceof MySQLDatabase) && (statement.getRemarks() != null)) {sql += " COMMENT='"+database.escapeStringForDatabase(statement.getRemarks())+"' ";}additionalSql.add(0, new UnparsedSql(sql, getAffectedTable(statement)));return additionalSql.toArray(new Sql[additionalSql.size()]);}

4.达梦不支持liquibase xm中的loadData标签需要做适配修改ModifyDataTypeGenerator类

    protected String getModifyString(Database database) {if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase) || (database instanceofMySQLDatabase) || (database instanceof OracleDatabase) || (database instanceof InformixDatabase) || (database instanceof DMDatabase)) {return "MODIFY";} else {return "ALTER COLUMN";}}protected String getPreDataTypeString(Database database) {if ((database instanceof DerbyDatabase) || (database instanceof AbstractDb2Database)) {return " SET DATA TYPE ";} else if ((database instanceof SybaseASADatabase) || (database instanceof SybaseDatabase) || (databaseinstanceof MSSQLDatabase) || (database instanceof MySQLDatabase) || (database instanceof HsqlDatabase) ||(database instanceof H2Database) || (database instanceof OracleDatabase) || (database instanceofInformixDatabase) || (database instanceof DMDatabase )) {return " ";} else {return " TYPE ";}}

关于达梦数据库的问题可以去达梦社区提问https://eco.dameng.com/community/question/


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部