Ruoyi and flowbale Dameng’s localized database transformation_the most detailed on the entire network

Springboot and flowable—Dameng’s localization transformation

Article directory

First of all, this example contains

1. Dameng database migration

2. SpringBoot and flowable workflow (flowable version is 6.7.0) replace Dameng database

3. SQL replacement in xml

This article should be the most detailed on the entire Internet, right? Bookmark it~

The subsequent transformation and deployment of TongWeb will be written in another article of mine.

1. Download related software

Visit Dameng official website:

Dameng official website

1.1 Download visualization tools

First register an account

Download and select the specified version of the database management tool x86, win64

Unzip the compressed package

Double-click the .iso file and install setup.exe for fool-proof installation.

Note: Click to initialize

Create database instance

Keep going to the next step and finish.

After installation, there will be these software, as follows: Generally used are database management tools and migration tools.

ps: The username and password of the administrator in the database management tool are both SYSDBA

Note that Damengdatabase namecorresponds to the createduser name, mode corresponds to the database , that is, user object, but a Users may also create multiple schemas, so it may be necessary to specify the default schema (database) in the Springboot project configuration file.

2. Source code execution

First get the initial code of the project to be modified and run it to ensure that it is feasible before modification.

2.1 Import sql

omission

2.2 Open the project and import pom dependencies

If the installation has the following problems:

This problem is usually caused by a problem with the test class under test, causing compilation failure. For example, executing the command mvn test on the console

The error is reported as follows:

**Solution:** When compiling install, skip the execution of test first. You need to add the following configuration in pom.xml so that test errors do not affect the compilation of the project.

Add the following dependencies to pom

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <testFailureIgnore>true</testFailureIgnore>
            </configuration>
        </plugin>
    </plugins>
</build>

After adding, clean install and then recompile, click the m icon and enter mvn idea:idea

2.3 Modify configuration

2.3.1 Modify database configuration

2.3.2 Modify redis configuration

2.3.3 Running the backend

Run directly

2.3.4 Running the front end

First open the front-end console and download the dependencies

npm install 

Then modify the proxy configuration in the vue.config.js configuration file (the proxy address here is the address to access the backend interface), and connect to the backend

Then save ctrl+s, be sure to remember to save the configuration to take effect.

npm run dev

3. Database migration

Migrate the local mysql database to Dameng database. (First of all, in order not to affect the previous project code when migrating here, I chose to backup the source code and Create a new backup of a mysql database, and modify the configuration connection in yml, which will be introduced in detail below)

For migration, I chose to use the Dameng database migration tool installed above.

3.1 Create a new Dameng database (user)

As mentioned above, Dameng's database corresponds to the user object, so now create a new user (database)

The username here is the database name, which can only be in uppercase letters, and the password is the user password similar to mysql.

3.1.1 User authorization

System authorization

Click OK. A failure message will appear here. Don’t worry about it. Refresh the user after closing. The new user has been successfully created.

At this point, the user and database have been created. The schema corresponds to the database. There are corresponding database tables inside.

3.2 Use database migration tools

The SYSDBA password defaults to SYSDBA

3.2.1 New construction

3.2.2 New migration

Click next

Select mysql to dm, next step.

To connect to the source mysql database, first specify the driver

Download the mysql driver locally first

mysql driver

Link: https://pan.baidu.com/s/1nRELoWeRzcklpEtK8MNtYA
Extraction code: 1111

Complete the next step

In the same way, specify the Dameng driver and database

Dameng driver link: https://pan.baidu.com/s/1CDg2nMwY0s94Lp3gQ3j2cQ
Extraction code: 1111

Next step

Uncheck Use default data type mapping relationship, and then click the Configure type mapping relationship button on the right
Click on the lower right corner to add, the original data type name is VARCHAR, the destination data type name is VARCHAR, and the destination Enter 4 for the accuracy expansion factor and confirm

Select the Dameng database (schema) that needs to be migrated to, next step

Select the specified table and click Next

Click Finish

There is an error message here, the record is too long

Solution: First execute the script to set the table to record super-long records under Dameng, delete the data and then migrate the table data again (modify the table in Dameng database management tool).

# 选择模式
set schema TRADING_CENTER_DM;
alter table SYS_OPER_LOG enable using long row;
truncate table SYS_OPER_LOG;
select * from SYS_OPER_LOG;

Go back to the migration tool. In the previous step, select the mode and select the table to migrate the failed table again.

The database migration is complete here.

4. Replace springboot with Dameng database

4.1 Install Dameng driver jar package

The jar package address was sent when migrating above.

Install the jar package into the maven repository

mvn install:install-file -Dfile=E:\Dameng\DmJdbcDriver18.jar -DgroupId=com.dm -DartifactId=DmJdbcDriver18 -Dversion=1.8 -Dpackaging=jar

4.2 POM adds Dameng’s driver dependency

Add Dameng’s driver dependency inadmin module

	<!-- DM8 jdbc -->
    <dependency>
        <groupId>com.dm</groupId>
        <artifactId>DmJdbcDriver18</artifactId>
        <version>1.8</version>
    </dependency>

At this time, you will encounter a compilation error when restarting the project. It can be started before adding the pom dependency. After adding the pom dependency, you will get an error when starting the compile and build. So first modify the connection driver yml configuration.

4.3 Modify the Dameng connection driver of yml

# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
#        driverClassName: com.mysql.cj.jdbc.Driver
        driverClassName: dm.jdbc.driver.DmDriver
        druid:
            # 主库数据源
#            master:
#                url: jdbc:mysql://121.43.234.114:3306/trading_center?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#                username: root
#                password: gds12345678
             #主库数据源(本地mysql数据库)
#            master:
#                url: jdbc:mysql://localhost:3306/trading_center_dm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#                username: root
#                password: 123
            # 主库数据源(本地达梦数据库)
            master:
                url: jdbc:dm://127.0.0.1:5236?TRADING_CENTER_DM&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
                username: SYSDBA
                password: SYSDBA
            # 从库数据源
            slave:
                # 从数据源开关/默认关闭
                enabled: false
                url:
                username:
                password:
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # 控制台管理用户名和密码
                login-username: ruoyi
                login-password: 123456
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true

Refer to the above modifications, rememberDameng database name is user name< a i=4>.

Note that the format of the database in the url is ? The database name is different from mysql, otherwise the URL will have the following network communication exception.

Error message:

16:46:16.112 [restartedMain] ERROR c.a.d.p.DruidDataSource - [init,931] - init datasource error, url: jdbc:dm://127.0.0.1:5236/TRADING_CENTER_DM?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8
dm.jdbc.driver.DMException: 网络通信异常
	at dm.jdbc.driver.DBError.throwException(DBError.java:774)
	at dm.jdbc.a.a.init(DBAccess.java:185)
	at dm.jdbc.a.a.<init>(DBAccess.java:157)
	at dm.jdbc.driver.DmdbConnection.openConnection(DmdbConnection.java:638)
	at dm.jdbc.desc.EP.connect(EP.java:159)
	at dm.jdbc.desc.EPGroup$EPSelector.select(EPGroup.java:395)
	at dm.jdbc.desc.EPGroup.connect(EPGroup.java:278)
	at dm.jdbc.driver.DmDriver.do_connect(DmDriver.java:163)
	at dm.jdbc.driver.DmDriver.connect(DmDriver.java:449)
	at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:156)
	at com.alibaba.druid.filter.stat.StatFilter.connection_connect(StatFilter.java:251)
	at com.alibaba.druid.filter.FilterChainImpl.connection_connect(FilterChainImpl.java:150)

Since this project uses flowable, after startup, an error message stating that the workflow cannot find the driver type will appear as follows:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngine': FactoryBean threw exception on object creation; nested exception is org.flowable.common.engine.api.FlowableException: couldn't deduct database type from database product name 'DM DBMS'

So we still have to modify flowable to integrate Dameng.

5. Flowable workflow integrates Dameng database

For pom dependencies and modifications to the Dameng driver, please refer to the above introduction. The following mainly introduces the integration of flowable with Dameng. (The version of flowable is 6.7.0)

When automatically loading the data source, flowable cannot identify the DM database type and uses overwriting the source code (that is, creating the same path as the source code class under the java package path, copying all the source code into this class, and then modifying Dameng's code ). To set the database type to MySQL or Oracle, you need to modify the file:

5.1 Modify the AbstractEngineConfiguration file

Create the org.flowable.common.engine.impl.AbstractEngineConfiguration file in the project (the paths here must be consistent, the source files will be overwritten when packaging), modify the getDefaultDatabaseTypeMappings method, and identify the Dameng database as mysql (value Setting the value to other values ​​will report a null pointer error. So it is common to mysql),After copying the source code, modify the method in the source code, as follows

public static final String DATABASE_TYPE_DM = "mysql"; //达梦 value值设置为其他值会报错空指针。所以通用mysql

public static Properties getDefaultDatabaseTypeMappings() {
    
    
        Properties databaseTypeMappings = new Properties();
        databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2);
        databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL);
        databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL);
        databaseTypeMappings.setProperty("MariaDB", DATABASE_TYPE_MYSQL);
        databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE);
        databaseTypeMappings.setProperty(PRODUCT_NAME_POSTGRES, DATABASE_TYPE_POSTGRES);
        databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL);
        databaseTypeMappings.setProperty(DATABASE_TYPE_DB2, DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/NT", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/NT64", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2 UDP", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/LINUX", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/LINUX390", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/LINUXX8664", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/LINUXZ64", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/LINUXPPC64", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/LINUXPPC64LE", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/400 SQL", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/6000", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2 UDB iSeries", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/AIX64", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/HPUX", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/HP64", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/SUN", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/SUN64", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/PTX", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2/2", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2);
        databaseTypeMappings.setProperty(PRODUCT_NAME_CRDB, DATABASE_TYPE_COCKROACHDB);
        databaseTypeMappings.setProperty("DM DBMS", DATABASE_TYPE_DM);// 加入达梦支持
        return databaseTypeMappings;
    }

5.2 modificationliquibase-core-4.3.5.jar Nakagento

Create the DmDatabase class in the java folder,The full path is liquibase.database.core.DmDatabase, refer to liquibase.database.core .OracleDatabase class, paste the following code directly into the newly created class.

The changes introduced by the author in this class are as follows:

Delete the setConnection method;
Modify the PRODUCT_NAME constant value to "DM DBMS";
Modify the getDefaultPort method to return 5236;
Modify the getShortName method to return dm;
Modify the getDefaultDriver method to return Dameng’s Driver;

The following code can be copied directly from mine. Note that the above code needs to be modified by yourself.

package liquibase.database.core;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import liquibase.CatalogAndSchema;
import liquibase.Scope;
import liquibase.database.AbstractJdbcDatabase;
import liquibase.database.DatabaseConnection;
import liquibase.database.OfflineConnection;
import liquibase.database.jvm.JdbcConnection;
import liquibase.exception.DatabaseException;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.exception.ValidationErrors;
import liquibase.executor.ExecutorService;
import liquibase.statement.DatabaseFunction;
import liquibase.statement.SequenceCurrentValueFunction;
import liquibase.statement.SequenceNextValueFunction;
import liquibase.statement.core.RawCallStatement;
import liquibase.statement.core.RawSqlStatement;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Catalog;
import liquibase.structure.core.Index;
import liquibase.structure.core.PrimaryKey;
import liquibase.structure.core.Schema;
import liquibase.util.JdbcUtils;
import liquibase.util.StringUtil;

public class DmDatabase extends AbstractJdbcDatabase {
    
    
    private static final String PRODUCT_NAME = "DM DBMS";

    @Override
    protected String getDefaultDatabaseProductName() {
    
    
        return PRODUCT_NAME;
    }

    /**
     * Is this AbstractDatabase subclass the correct one to use for the given connection.
     *
     * @param conn
     */
    @Override
    public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
    
    
        return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName());
    }

    /**
     * If this database understands the given url, return the default driver class name.  Otherwise return null.
     *
     * @param url
     */
    @Override
    public String getDefaultDriver(String url) {
    
    
        if (url.startsWith("jdbc:dm")) {
    
    
            return "dm.jdbc.driver.DmDriver";
        }

        return null;
    }

    /**
     * Returns an all-lower-case short name of the product.  Used for end-user selecting of database type
     * such as the DBMS precondition.
     */
    @Override
    public String getShortName() {
    
    
        return "dm";
    }

    @Override
    public Integer getDefaultPort() {
    
    
        return 5236;
    }

    /**
     * Returns whether this database support initially deferrable columns.
     */
    @Override
    public boolean supportsInitiallyDeferrableColumns() {
    
    
        return true;
    }

    @Override
    public boolean supportsTablespaces() {
    
    
        return true;
    }

    @Override
    public int getPriority() {
    
    
        return PRIORITY_DEFAULT;
    }

    private static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*");

    protected final int SHORT_IDENTIFIERS_LENGTH = 30;
    protected final int LONG_IDENTIFIERS_LEGNTH = 128;
    public static final int ORACLE_12C_MAJOR_VERSION = 12;

    private Set<String> reservedWords = new HashSet<>();
    private Set<String> userDefinedTypes;
    private Map<String, String> savedSessionNlsSettings;

    private Boolean canAccessDbaRecycleBin;
    private Integer databaseMajorVersion;
    private Integer databaseMinorVersion;

    /**
     * Default constructor for an object that represents the Oracle Database DBMS.
     */
    public DmDatabase() {
    
    
        super.unquotedObjectsAreUppercased = true;
        //noinspection HardCodedStringLiteral
        super.setCurrentDateTimeFunction("SYSTIMESTAMP");
        // Setting list of Oracle's native functions
        //noinspection HardCodedStringLiteral
        dateFunctions.add(new DatabaseFunction("SYSDATE"));
        //noinspection HardCodedStringLiteral
        dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP"));
        //noinspection HardCodedStringLiteral
        dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP"));
        //noinspection HardCodedStringLiteral
        super.sequenceNextValueFunction = "%s.nextval";
        //noinspection HardCodedStringLiteral
        super.sequenceCurrentValueFunction = "%s.currval";
    }

    private void tryProxySession(final String url, final Connection con) {
    
    
        Matcher m = PROXY_USER.matcher(url);
        if (m.matches()) {
    
    
            Properties props = new Properties();
            props.put("PROXY_USER_NAME", m.group(1));
            try {
    
    
                Method method = con.getClass().getMethod("openProxySession", int.class, Properties.class);
                method.setAccessible(true);
                method.invoke(con, 1, props);
            } catch (Exception e) {
    
    
                Scope.getCurrentScope().getLog(getClass()).info("Could not open proxy session on OracleDatabase: " + e.getCause().getMessage());
            }
        }
    }

    @Override
    public int getDatabaseMajorVersion() throws DatabaseException {
    
    
        if (databaseMajorVersion == null) {
    
    
            return super.getDatabaseMajorVersion();
        } else {
    
    
            return databaseMajorVersion;
        }
    }

    @Override
    public int getDatabaseMinorVersion() throws DatabaseException {
    
    
        if (databaseMinorVersion == null) {
    
    
            return super.getDatabaseMinorVersion();
        } else {
    
    
            return databaseMinorVersion;
        }
    }

    @Override
    public String getJdbcCatalogName(CatalogAndSchema schema) {
    
    
        return null;
    }

    @Override
    public String getJdbcSchemaName(CatalogAndSchema schema) {
    
    
        return correctObjectName((schema.getCatalogName() == null) ? schema.getSchemaName() : schema.getCatalogName(), Schema.class);
    }

    @Override
    protected String getAutoIncrementClause(final String generationType, final Boolean defaultOnNull) {
    
    
        if (StringUtil.isEmpty(generationType)) {
    
    
            return super.getAutoIncrementClause();
        }

        String autoIncrementClause = "GENERATED %s AS IDENTITY"; // %s -- [ ALWAYS | BY DEFAULT [ ON NULL ] ]
        String generationStrategy = generationType;
        if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) {
    
    
            generationStrategy += " ON NULL";
        }
        return String.format(autoIncrementClause, generationStrategy);
    }

    @Override
    public String generatePrimaryKeyName(String tableName) {
    
    
        if (tableName.length() > 27) {
    
    
            //noinspection HardCodedStringLiteral
            return "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27);
        } else {
    
    
            //noinspection HardCodedStringLiteral
            return "PK_" + tableName.toUpperCase(Locale.US);
        }
    }

    @Override
    public boolean isReservedWord(String objectName) {
    
    
        return reservedWords.contains(objectName.toUpperCase());
    }

    @Override
    public boolean supportsSequences() {
    
    
        return true;
    }

    /**
     * Oracle supports catalogs in liquibase terms
     *
     * @return false
     */
    @Override
    public boolean supportsSchemas() {
    
    
        return false;
    }

    @Override
    protected String getConnectionCatalogName() throws DatabaseException {
    
    
        if (getConnection() instanceof OfflineConnection) {
    
    
            return getConnection().getCatalog();
        }
        try {
    
    
            //noinspection HardCodedStringLiteral
            return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class);
        } catch (Exception e) {
    
    
            //noinspection HardCodedStringLiteral
            Scope.getCurrentScope().getLog(getClass()).info("Error getting default schema", e);
        }
        return null;
    }

    @Override
    public String getDefaultCatalogName() {
    
    //NOPMD
        return (super.getDefaultCatalogName() == null) ? null : super.getDefaultCatalogName().toUpperCase(Locale.US);
    }

    /**
     * <p>Returns an Oracle date literal with the same value as a string formatted using ISO 8601.</p>
     *
     * <p>Convert an ISO8601 date string to one of the following results:
     * to_date('1995-05-23', 'YYYY-MM-DD')
     * to_date('1995-05-23 09:23:59', 'YYYY-MM-DD HH24:MI:SS')</p>
     * <p>
     * Implementation restriction:<br>
     * Currently, only the following subsets of ISO8601 are supported:<br>
     * <ul>
     * <li>YYYY-MM-DD</li>
     * <li>YYYY-MM-DDThh:mm:ss</li>
     * </ul>
     */
    @Override
    public String getDateLiteral(String isoDate) {
    
    
        String normalLiteral = super.getDateLiteral(isoDate);

        if (isDateOnly(isoDate)) {
    
    
            return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')";
        } else if (isTimeOnly(isoDate)) {
    
    
            return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')";
        } else if (isTimestamp(isoDate)) {
    
    
            return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')";
        } else if (isDateTime(isoDate)) {
    
    
            int seppos = normalLiteral.lastIndexOf('.');
            if (seppos != -1) {
    
    
                normalLiteral = normalLiteral.substring(0, seppos) + "'";
            }
            return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')";
        }
        return "UNSUPPORTED:" + isoDate;
    }

    @Override
    public boolean isSystemObject(DatabaseObject example) {
    
    
        if (example == null) {
    
    
            return false;
        }

        if (this.isLiquibaseObject(example)) {
    
    
            return false;
        }

        if (example instanceof Schema) {
    
    
            //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
            if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) {
    
    
                return true;
            }
            //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
            if ("SYSTEM".equals(example.getSchema().getCatalogName()) || "SYS".equals(example.getSchema().getCatalogName()) || "CTXSYS".equals(example.getSchema().getCatalogName()) || "XDB".equals(example.getSchema().getCatalogName())) {
    
    
                return true;
            }
        } else if (isSystemObject(example.getSchema())) {
    
    
            return true;
        }
        if (example instanceof Catalog) {
    
    
            //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
            if (("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName()))) {
    
    
                return true;
            }
        } else if (example.getName() != null) {
    
    
            //noinspection HardCodedStringLiteral
            if (example.getName().startsWith("BIN$")) {
    
     //oracle deleted table
                boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin();
                if (!filteredInOriginalQuery) {
    
    
                    filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName());
                }

                if (filteredInOriginalQuery) {
    
    
                    return !((example instanceof PrimaryKey) || (example instanceof Index) || (example instanceof
                            liquibase.statement.UniqueConstraint));
                } else {
    
    
                    return true;
                }
            } else //noinspection HardCodedStringLiteral
                if (example.getName().startsWith("AQ$")) {
    
     //oracle AQ tables
                    return true;
                } else //noinspection HardCodedStringLiteral
                    if (example.getName().startsWith("DR$")) {
    
     //oracle index tables
                        return true;
                    } else //noinspection HardCodedStringLiteral
                        if (example.getName().startsWith("SYS_IOT_OVER")) {
    
     //oracle system table
                            return true;
                        } else //noinspection HardCodedStringLiteral,HardCodedStringLiteral
                            if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) {
    
    
                                // CORE-1768 - Oracle creates these for spatial indices and will remove them when the index is removed.
                                return true;
                            } else //noinspection HardCodedStringLiteral
                                if (example.getName().startsWith("MLOG$_")) {
    
     //Created by materliaized view logs for every table that is part of a materialized view. Not available for DDL operations.
                                    return true;
                                } else //noinspection HardCodedStringLiteral
                                    if (example.getName().startsWith("RUPD$_")) {
    
     //Created by materialized view log tables using primary keys. Not available for DDL operations.
                                        return true;
                                    } else //noinspection HardCodedStringLiteral
                                        if (example.getName().startsWith("WM$_")) {
    
     //Workspace Manager backup tables.
                                            return true;
                                        } else //noinspection HardCodedStringLiteral
                                            if ("CREATE$JAVA$LOB$TABLE".equals(example.getName())) {
    
     //This table contains the name of the Java object, the date it was loaded, and has a BLOB column to store the Java object.
                                                return true;
                                            } else //noinspection HardCodedStringLiteral
                                                if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) {
    
     //This is a hash table that tracks the loading of Java objects into a schema.
                                                    return true;
                                                } else //noinspection HardCodedStringLiteral
                                                    if (example.getName().startsWith("ISEQ$$_")) {
    
     //System-generated sequence
                                                        return true;
                                                    } else //noinspection HardCodedStringLiteral
                                                        if (example.getName().startsWith("USLOG$")) {
    
     //for update materialized view
                                                            return true;
                                                        } else if (example.getName().startsWith("SYS_FBA")) {
    
     //for Flashback tables
                                                            return true;
                                                        }
        }

        return super.isSystemObject(example);
    }

    @Override
    public boolean supportsAutoIncrement() {
    
    
        // Oracle supports Identity beginning with version 12c
        boolean isAutoIncrementSupported = false;

        try {
    
    
            if (getDatabaseMajorVersion() >= 12) {
    
    
                isAutoIncrementSupported = true;
            }

            // Returning true will generate create table command with 'IDENTITY' clause, example:
            // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) GENERATED BY DEFAULT AS IDENTITY NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));

            // While returning false will continue to generate create table command without 'IDENTITY' clause, example:
            // CREATE TABLE AutoIncTest (IDPrimaryKey NUMBER(19) NOT NULL, TypeID NUMBER(3) NOT NULL, Description NVARCHAR2(50), CONSTRAINT PK_AutoIncTest PRIMARY KEY (IDPrimaryKey));

        } catch (DatabaseException ex) {
    
    
            isAutoIncrementSupported = false;
        }

        return isAutoIncrementSupported;
    }


//    public Set<UniqueConstraint> findUniqueConstraints(String schema) throws DatabaseException {
    
    
//        Set<UniqueConstraint> returnSet = new HashSet<UniqueConstraint>();
//
//        List<Map> maps = new Executor(this).queryForList(new RawSqlStatement("SELECT UC.CONSTRAINT_NAME, UCC.TABLE_NAME, UCC.COLUMN_NAME FROM USER_CONSTRAINTS UC, USER_CONS_COLUMNS UCC WHERE UC.CONSTRAINT_NAME=UCC.CONSTRAINT_NAME AND CONSTRAINT_TYPE='U' ORDER BY UC.CONSTRAINT_NAME"));
//
//        UniqueConstraint constraint = null;
//        for (Map map : maps) {
    
    
//            if (constraint == null || !constraint.getName().equals(constraint.getName())) {
    
    
//                returnSet.add(constraint);
//                Table table = new Table((String) map.get("TABLE_NAME"));
//                constraint = new UniqueConstraint(map.get("CONSTRAINT_NAME").toString(), table);
//            }
//        }
//        if (constraint != null) {
    
    
//            returnSet.add(constraint);
//        }
//
//        return returnSet;
//    }

    @Override
    public boolean supportsRestrictForeignKeys() {
    
    
        return false;
    }

    @Override
    public int getDataTypeMaxParameters(String dataTypeName) {
    
    
        //noinspection HardCodedStringLiteral
        if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) {
    
    
            return 0;
        }
        //noinspection HardCodedStringLiteral
        if ("BINARY_DOUBLE".equals(dataTypeName.toUpperCase())) {
    
    
            return 0;
        }
        return super.getDataTypeMaxParameters(dataTypeName);
    }

    public String getSystemTableWhereClause(String tableNameColumn) {
    
    
        List<String> clauses = new ArrayList<String>(Arrays.asList("BIN$",
                "AQ$",
                "DR$",
                "SYS_IOT_OVER",
                "MLOG$_",
                "RUPD$_",
                "WM$_",
                "ISEQ$$_",
                "USLOG$",
                "SYS_FBA"));

        for (int i = 0; i < clauses.size(); i++) {
    
    
            clauses.set(i, tableNameColumn + " NOT LIKE '" + clauses.get(i) + "%'");
        }
        return "(" + StringUtil.join(clauses, " AND ") + ")";
    }

    @Override
    public boolean jdbcCallsCatalogsSchemas() {
    
    
        return true;
    }

    public Set<String> getUserDefinedTypes() {
    
    
        if (userDefinedTypes == null) {
    
    
            userDefinedTypes = new HashSet<>();
            if ((getConnection() != null) && !(getConnection() instanceof OfflineConnection)) {
    
    
                try {
    
    
                    try {
    
    
                        //noinspection HardCodedStringLiteral
                        userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class));
                    } catch (DatabaseException e) {
    
     //fall back to USER_TYPES if the user cannot see ALL_TYPES
                        //noinspection HardCodedStringLiteral
                        userDefinedTypes.addAll(Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class));
                    }
                } catch (DatabaseException e) {
    
    
                    //ignore error
                }
            }
        }

        return userDefinedTypes;
    }

    @Override
    public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) {
    
    
        //noinspection HardCodedStringLiteral
        if ((databaseFunction != null) && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) {
    
    
            return databaseFunction.toString();
        }
        if ((databaseFunction instanceof SequenceNextValueFunction) || (databaseFunction instanceof
                SequenceCurrentValueFunction)) {
    
    
            String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction);
            // replace "myschema.my_seq".nextval with "myschema"."my_seq".nextval
            return quotedSeq.replaceFirst("\"([^\\.\"]+)\\.([^\\.\"]+)\"", "\"$1\".\"$2\"");

        }

        return super.generateDatabaseFunctionValue(databaseFunction);
    }

    @Override
    public ValidationErrors validate() {
    
    
        ValidationErrors errors = super.validate();
        DatabaseConnection connection = getConnection();
        if ((connection == null) || (connection instanceof OfflineConnection)) {
    
    
            //noinspection HardCodedStringLiteral
            Scope.getCurrentScope().getLog(getClass()).info("Cannot validate offline database");
            return errors;
        }

        if (!canAccessDbaRecycleBin()) {
    
    
            errors.addWarning(getDbaRecycleBinWarning());
        }

        return errors;

    }

    public String getDbaRecycleBinWarning() {
    
    
        //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral,
        // HardCodedStringLiteral
        //noinspection HardCodedStringLiteral,HardCodedStringLiteral,HardCodedStringLiteral
        return "Liquibase needs to access the DBA_RECYCLEBIN table so we can automatically handle the case where " +
                "constraints are deleted and restored. Since Oracle doesn't properly restore the original table names " +
                "referenced in the constraint, we use the information from the DBA_RECYCLEBIN to automatically correct this" +
                " issue.\n" +
                "\n" +
                "The user you used to connect to the database (" + getConnection().getConnectionUserName() +
                ") needs to have \"SELECT ON SYS.DBA_RECYCLEBIN\" permissions set before we can perform this operation. " +
                "Please run the following SQL to set the appropriate permissions, and try running the command again.\n" +
                "\n" +
                "     GRANT SELECT ON SYS.DBA_RECYCLEBIN TO " + getConnection().getConnectionUserName() + ";";
    }

    public boolean canAccessDbaRecycleBin() {
    
    
        if (canAccessDbaRecycleBin == null) {
    
    
            DatabaseConnection connection = getConnection();
            if ((connection == null) || (connection instanceof OfflineConnection)) {
    
    
                return false;
            }

            Statement statement = null;
            try {
    
    
                statement = ((JdbcConnection) connection).createStatement();
                @SuppressWarnings("HardCodedStringLiteral") ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1");
                resultSet.close(); //don't need to do anything with the result set, just make sure statement ran.
                this.canAccessDbaRecycleBin = true;
            } catch (Exception e) {
    
    
                //noinspection HardCodedStringLiteral
                if ((e instanceof SQLException) && e.getMessage().startsWith("ORA-00942")) {
    
     //ORA-00942: table or view does not exist
                    this.canAccessDbaRecycleBin = false;
                } else {
    
    
                    //noinspection HardCodedStringLiteral
                    Scope.getCurrentScope().getLog(getClass()).warning("Cannot check dba_recyclebin access", e);
                    this.canAccessDbaRecycleBin = false;
                }
            } finally {
    
    
                JdbcUtils.close(null, statement);
            }
        }

        return canAccessDbaRecycleBin;
    }

    @Override
    public boolean supportsNotNullConstraintNames() {
    
    
        return true;
    }

    /**
     * Tests if the given String would be a valid identifier in Oracle DBMS. In Oracle, a valid identifier has
     * the following form (case-insensitive comparison):
     * 1st character: A-Z
     * 2..n characters: A-Z0-9$_#
     * The maximum length of an identifier differs by Oracle version and object type.
     */
    public boolean isValidOracleIdentifier(String identifier, Class<? extends DatabaseObject> type) {
    
    
        if ((identifier == null) || (identifier.length() < 1))
            return false;

        if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$"))
            return false;

        /*
         * @todo It seems we currently do not have a class for tablespace identifiers, and all other classes
         * we do know seem to be supported as 12cR2 long identifiers, so:
         */
        return (identifier.length() <= LONG_IDENTIFIERS_LEGNTH);
    }

    /**
     * Returns the maximum number of bytes (NOT: characters) for an identifier. For Oracle <=12c Release 20, this
     * is 30 bytes, and starting from 12cR2, up to 128 (except for tablespaces, PDB names and some other rather rare
     * object types).
     *
     * @return the maximum length of an object identifier, in bytes
     */
    public int getIdentifierMaximumLength() {
    
    
        try {
    
    
            if (getDatabaseMajorVersion() < ORACLE_12C_MAJOR_VERSION) {
    
    
                return SHORT_IDENTIFIERS_LENGTH;
            } else if ((getDatabaseMajorVersion() == ORACLE_12C_MAJOR_VERSION) && (getDatabaseMinorVersion() <= 1)) {
    
    
                return SHORT_IDENTIFIERS_LENGTH;
            } else {
    
    
                return LONG_IDENTIFIERS_LEGNTH;
            }
        } catch (DatabaseException ex) {
    
    
            throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", ex);
        }

    }
}

5.3 Modify the liquibase.datatype.core.BooleanType class

In the same way, copy the source code to overwrite the modifications.

Add DmDatabase support in toDatabaseDataType method
Add DmDatabase type in isNumericBoolean method
The specific code is as follows: you can copy it directly

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package liquibase.datatype.core;

import java.util.Locale;

import liquibase.change.core.LoadDataChange;
import liquibase.change.core.LoadDataChange.LOAD_DATA_TYPE;
import liquibase.database.Database;
import liquibase.database.core.*;
import liquibase.datatype.DataTypeInfo;
import liquibase.datatype.DatabaseDataType;
import liquibase.datatype.LiquibaseDataType;
import liquibase.exception.UnexpectedLiquibaseException;
import liquibase.statement.DatabaseFunction;
import liquibase.util.StringUtil;

@DataTypeInfo(
        name = "boolean",
        aliases = {"java.sql.Types.BOOLEAN", "java.lang.Boolean", "bit", "bool"},
        minParameters = 0,
        maxParameters = 0,
        priority = 1
)
public class BooleanType extends LiquibaseDataType {
    public BooleanType() {
    }

    @Override
    public DatabaseDataType toDatabaseDataType(Database database) {
        String originalDefinition = StringUtil.trimToEmpty(getRawDefinition());
        if ((database instanceof Firebird3Database)) {
            return new DatabaseDataType("BOOLEAN");
        }

        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.getClass().isAssignableFrom(DB2Database.class)) {
            if (((DB2Database) 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());
            }
        } else if(database instanceof DmDatabase) {
            return new DatabaseDataType("bit");
        }

        return super.toDatabaseDataType(database);
    }

    @Override
    public String objectToSql(Object value, Database database) {
        if ((value == null) || "null".equals(value.toString().toLowerCase(Locale.US))) {
            return null;
        }

        String returnValue;
        if (value instanceof String) {
            value = ((String) value).replaceAll("'", "");
            if ("true".equals(((String) value).toLowerCase(Locale.US)) || "1".equals(value) || "b'1'".equals(((String) value).toLowerCase(Locale.US)) || "t".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getTrueBooleanValue(database).toLowerCase(Locale.US))) {
                returnValue = this.getTrueBooleanValue(database);
            } else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals(
                    ((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) {
                returnValue = this.getFalseBooleanValue(database);
            } else {
                throw new UnexpectedLiquibaseException("Unknown boolean value: " + value);
            }
        } else if (value instanceof Long) {
            if (Long.valueOf(1).equals(value)) {
                returnValue = this.getTrueBooleanValue(database);
            } else {
                returnValue = this.getFalseBooleanValue(database);
            }
        } else if (value instanceof Number) {
            if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) {
                returnValue = this.getTrueBooleanValue(database);
            } else {
                returnValue = this.getFalseBooleanValue(database);
            }
        } else if (value instanceof DatabaseFunction) {
            return value.toString();
        } else if (value instanceof Boolean) {
            if (((Boolean) value)) {
                returnValue = this.getTrueBooleanValue(database);
            } else {
                returnValue = this.getFalseBooleanValue(database);
            }
        } else {
            throw new UnexpectedLiquibaseException("Cannot convert type " + value.getClass() + " to a boolean value");
        }

        return returnValue;
    }

    protected boolean isNumericBoolean(Database database) {
        if (database instanceof DerbyDatabase) {
            return !((DerbyDatabase) database).supportsBooleanDataType();
        } else if (database.getClass().isAssignableFrom(DB2Database.class)) {
            return !((DB2Database) database).supportsBooleanDataType();
        }
        return (database instanceof Db2zDatabase) || (database instanceof DB2Database) || (database instanceof FirebirdDatabase) || (database instanceof
                MSSQLDatabase) || (database instanceof MySQLDatabase) || (database instanceof OracleDatabase) ||
                (database instanceof SQLiteDatabase) || (database instanceof SybaseASADatabase) || (database instanceof
                SybaseDatabase) || (database instanceof DmDatabase);
    }

    /**
     * The database-specific value to use for "false" "boolean" columns.
     */
    public String getFalseBooleanValue(Database database) {
        if (isNumericBoolean(database)) {
            return "0";
        }
        if (database instanceof InformixDatabase) {
            return "'f'";
        }
        return "FALSE";
    }


    /**
     * The database-specific value to use for "true" "boolean" columns.
     */
    public String getTrueBooleanValue(Database database) {
        if (isNumericBoolean(database)) {
            return "1";
        }
        if (database instanceof InformixDatabase) {
            return "'t'";
        }
        return "TRUE";
    }


    @Override
    public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() {
        return LoadDataChange.LOAD_DATA_TYPE.BOOLEAN;
    }
}

5.4 修改resources/META-INF.services/liquibase.database.Database

Add DmDatabase support. The modified file is as follows. Note that if you cannot find the source code, just use ctrl+shift+f to search globally. ( Also create the same file in this directory, don’t forget it, otherwise the project will not run!!!)

liquibase.database.core.CockroachDatabase
liquibase.database.core.DB2Database
liquibase.database.core.Db2zDatabase
liquibase.database.core.DerbyDatabase
liquibase.database.core.Firebird3Database
liquibase.database.core.FirebirdDatabase
liquibase.database.core.H2Database
liquibase.database.core.HsqlDatabase
liquibase.database.core.InformixDatabase
liquibase.database.core.Ingres9Database
liquibase.database.core.MSSQLDatabase
liquibase.database.core.MariaDBDatabase
liquibase.database.core.MockDatabase
liquibase.database.core.MySQLDatabase
liquibase.database.core.OracleDatabase
liquibase.database.core.PostgresDatabase
liquibase.database.core.SQLiteDatabase
liquibase.database.core.SybaseASADatabase
liquibase.database.core.SybaseDatabase
liquibase.database.core.DmDatabase
liquibase.database.core.UnsupportedDatabase

5.5 Error reporting

00:04:55.338 [restartedMain] ERROR o.f.c.e.i.d.CommonDbSchemaManager - [getProperty,198] - Could not get property from table ACT_GE_PROPERTY
dm.jdbc.driver.DMException: line 1 An error occurred near:
Invalid table or view name [ACT_GE_PROPERTY]

Error reporting solutions found online

Configure mysqlAdd: nullCatalogMeansCurrent=true when connecting. The final configuration is as follows

# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
#        driverClassName: com.mysql.cj.jdbc.Driver
        driverClassName: dm.jdbc.driver.DmDriver
        druid:
            # 主库数据源
#            master:
#                url: jdbc:mysql://121.43.234.114:3306/trading_center?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#                username: root
#                password: gds12345678
             #主库数据源(本地mysql数据库)
#            master:
#                url: jdbc:mysql://localhost:3306/trading_center_dm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
#                username: root
#                password: 123
            # 主库数据源(本地达梦数据库)
            master:
                url: jdbc:dm://127.0.0.1:5236?TRADING_CENTER_DM&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true
                username: TRADING_CENTER_DM
                password: TRADING_CENTER_DM
            # 从库数据源
            slave:
                # 从数据源开关/默认关闭
                enabled: false
                url:
                username:
                password:
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置检测连接是否有效
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # 控制台管理用户名和密码
                login-username: ruoyi
                login-password: 123456
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true

6. Replace and modify the sql in the project

Some function methods in mysql are not supported by Dameng, so some SQL should be replaced with methods supported by Dameng. (For more function differences, please see the official website documentation or the notes below this article)

The main modified xml sql in this project is as follows

Modified sql xml:

  • SysNoticeMapper.xml (case function modification)
  • GenTableColumnMapper.xml (modify the primary key of the insert statement of the gen_table_column table to increase automatically)
  • SysDeptMapper.xml (modify the primary key of the insert statement of the sys_dept table to increase automatically)
  • SysJobMapper.xml (modify the primary key of the insert statement of the sys_job table to increase automatically)
  • SysJobLogMapper.xml (modify the primary key of the insert statement of the sys_job_log table to increase automatically)
  • SysMenuMapper.xml (modify the primary key of the insert statement of the sys_menu table to increase automatically)
  • SysPostMapper.xml (modify the primary key of the insert statement of the sys_post table to increase automatically)
  • SysUserMapper.xml (modify the primary key of the insert statement of the sys_user table to increase automatically)
  • SysJobLogMapper.xml (modify and replace date_format function)
  • SysOperLogMapper.xml (modify and replace date_format function)
  • GenTableColumnMapper.xml (the sql generated by the code is modified to Dameng's writing method)

6.1 Replace the find_in_set function

Since Dameng database does not have a built-in find_in_set function, but it is used in the project, it is necessary to customize the function to facilitate subsequent program calls.

Switch mode first

set schema TRADING_CENTER_DM;

Create the function FIND_IN_SET again

CREATE OR REPLACE FUNCTION FIND_IN_SET
                (
                        piv_str1 varchar2,
                        piv_str2 varchar2,
                        p_sep    varchar2 := ',')
                RETURN NUMBER
                            IS
                l_idx     number:=0;                 -- 用于计算piv_str2中分隔符的位置
                str       varchar2(500);             -- 根据分隔符截取的子字符串
                piv_str   varchar2(500) := piv_str2; -- 将piv_str2赋值给piv_str
                res       number        :=0;         -- 返回结果
                loopIndex number        :=0;
        BEGIN
                -- 如果piv_str中没有分割符,直接判断piv_str1和piv_str是否相等,相等 res=1
                IF instr(piv_str, p_sep, 1) = 0 THEN
                        IF piv_str          = piv_str1 THEN
                                res        := 1;
                        END IF;
                ELSE
                        -- 循环按分隔符截取piv_str
                        LOOP
                                l_idx    := instr(piv_str, p_sep);
                                loopIndex:=loopIndex+1;
                                -- 当piv_str中还有分隔符时
                                IF l_idx > 0 THEN
                                        -- 截取第一个分隔符前的字段str
                                        str:= substr(piv_str, 1, l_idx-1);
                                        -- 判断 str 和piv_str1 是否相等,相等 res=1 并结束循环判断
                                        IF str      = piv_str1 THEN
                                                res:= loopIndex;
                                                EXIT;
                                        END IF;
                                        piv_str := substr(piv_str, l_idx+length(p_sep));
                                ELSE
                                        -- 当截取后的piv_str 中不存在分割符时,判断piv_str和piv_str1是否相等,相等 res=1
                                        IF piv_str  = piv_str1 THEN
                                                res:= loopIndex;
                                        END IF;
                                        -- 无论最后是否相等,都跳出循环
                                        EXIT;
                                END IF;
                        END LOOP;
                        -- 结束循环
                END IF;
                -- 返回res
                RETURN res;
        END FIND_IN_SET;
commit;

6.2 Replace case() function

cast(), mysq has it, Dameng does not.

cast(xxx as SIGNED INTEGER) -- mysql函数

替换为

to_number(xxx) -- 达梦函数

cast(notice_content as char)  --mysql函数 notice_content是longblob类型 转为了char
替换为
CONVERT(notice_content, SQL_CHAR)  --达梦函数 notice_content是blob类型 转为了char

6.3 Modify SQL according to Dameng’s primary key auto-increment

Dameng's primary key auto-increment does not allow that field name to appear in the INSERT INTO statement. Even if the value is null, an error will be reported.

mistake

INSERT INTO sys_logs_method ( Id, ActionTime, ActionBy, Type, IsDelete, Remark, Ip, ActionByName, ProjectNo, actionByAccount ) VALUES ( 0, ?, ?, ?, ?, ?, ?, ?, ?, ? ) 

mistake

INSERT INTO sys_logs_method ( Id, ActionTime, ActionBy, Type, IsDelete, Remark, Ip, ActionByName, ProjectNo, actionByAccount ) VALUES ( null, ?, ?, ?, ?, ?, ?, ?, ?, ? ) 

correct

INSERT INTO sys_logs_method ( ActionTime, ActionBy, Type, IsDelete, Remark, Ip, ActionByName, ProjectNo, actionByAccount ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? ) 

For details of the modified xml statements, see Table of Contents 6.

6.4 Modify and replace date_format function

Dameng does not support the date_sub function, use dateadd(datepart,n,date) instead, where datepart can be: year(yy,yyyy), quarter(qq,q), month(mm,m), dayofyear(dy,y) ), day(dd,d), week(wk,ww), weekday(dw), hour(hh), minute(mi,n), second(ss,s), millisecond(ms),

select dateadd(month, -6, now());  --dameng
select dateadd(month, 2, now());   --dameng

Replacement example:

 date_format(create_time,'%y%m%d')   --mysql
 替换为达梦
to_char(create_time, 'YYMMDD')       --dameng

6.5 case-when-then-else is not supported

case-when-then-else is not supported

Here is an example of case-when generated by code in the Zoey framework

mysql writing method

    <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
		select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else null end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
		from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
		order by ordinal_position
	</select>

Change your dream

<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
    select t3.COLUMN_NAME                     as column_name,
           (CASE
                WHEN (t3.NULLABLE = 'N' and t4.CONSTRAINT_TYPE !='P') THEN '1'
                ELSE NULL END)
                                              as is_required,
           IF(t4.CONSTRAINT_TYPE = 'P', 1, 0) as is_pk,
           t3.COLUMN_ID                       as sort,
           t5.COMMENTS                        as column_comment,
           (  CASE
                  WHEN (t3.TYPE = 'INT' OR t3.TYPE = 'INTEGER' OR t3.TYPE = 'BIGINT' OR t3.TYPE = 'TINYINT' OR
                        t3.TYPE = 'SMALLINT') and t4.CONSTRAINT_TYPE = 'P' THEN '1'
                  ELSE '0' END  )                 AS is_increment,
           DATA_TYPE as DATA_TYPE
    from ((select COLUMN_NAME,
                  COLUMN_ID,
                  concat(DATA_TYPE, '(', DATA_LENGTH, ')') as DATA_TYPE,
                  DATA_TYPE                                as TYPE,
                  TABLE_NAME,
                  NULLABLE
           from SYS.USER_TAB_COLUMNS
           WHERE table_name = (#{tableName})) t3
             left join (select COMMENTS, COLUMN_NAME, TABLE_NAME from SYS.USER_COL_COMMENTS) t5
                       ON (t3.COLUMN_NAME = t5.COLUMN_NAME and t3.TABLE_NAME = t5.TABLE_NAME)
             left join
         (select t1.CONSTRAINT_TYPE, t1.OWNER, t1.TABLE_NAME, t2.CONSTRAINT_NAME, t2.COLUMN_NAME
          from (select CONSTRAINT_NAME, CONSTRAINT_TYPE, OWNER, TABLE_NAME from SYS.USER_CONSTRAINTS) t1
                   inner join (select CONSTRAINT_NAME, OWNER, TABLE_NAME, COLUMN_NAME from SYS.USER_CONS_COLUMNS) t2
                              ON (t1.TABLE_NAME = t2.TABLE_NAME and t1.CONSTRAINT_NAME = t2.CONSTRAINT_NAME)
          where t1.CONSTRAINT_TYPE = 'P') t4 ON (t3.COLUMN_NAME = t4.COLUMN_NAME and t3.TABLE_NAME = t4.TABLE_NAME))
    order by t3.COLUMN_ID
</select>

If the code generation of the framework is used, there are several XML methods that also need to be replaced, as follows:

  <select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
        select t1.TABLE_NAME as table_name, t2.COMMENTS as table_comment, NULL as create_time, NULL as update_time
        from SYS.USER_TABLES t1
        inner join SYS.USER_TAB_COMMENTS t2 ON t1.TABLE_NAME = t2.TABLE_NAME
        WHERE t1.TABLE_NAME NOT LIKE 'qrtz_%'
        AND t1.TABLE_NAME NOT LIKE 'gen_%'
        AND t1.TABLE_NAME NOT IN (select table_name as TABLE_NAME from gen_table)
        <if test="tableName != null and tableName != ''">
            AND lower(t1.TABLE_NAME) like lower(concat('%', #{tableName}, '%'))
        </if>
        <if test="tableComment != null and tableComment != ''">
            AND lower(t1.TABLE_NAME) like lower(concat('%', #{tableName}, '%'))
        </if>
    </select>

 <select id="selectDbTableListByNames" resultMap="GenTableResult">
        select t1.TABLE_NAME as table_name, t2.COMMENTS as table_comment, NULL as create_time, NULL as update_time
        from SYS.USER_TABLES t1
        inner join SYS.USER_TAB_COMMENTS t2 ON t1.TABLE_NAME = t2.TABLE_NAME
        WHERE t1.TABLE_NAME NOT LIKE 'qrtz_%'
        AND t1.TABLE_NAME NOT LIKE 'gen_%'
        and t1.TABLE_NAME in
        <foreach collection="array" item="name" open="(" separator="," close=")">
            #{name}
        </foreach>
    </select>
                                                       
<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
    select t1.TABLE_NAME as table_name, t2.COMMENTS as table_comment, NULL as create_time, NULL as update_time
    from SYS.USER_TABLES t1
             inner join SYS.USER_TAB_COMMENTS t2 ON t1.TABLE_NAME = t2.TABLE_NAME
    where t2.COMMENTS <![CDATA[ <> ]]> ''
      and t1.TABLE_NAME = #{tableName}
</select>                                         

7. Notes

7.1 How to modify source code

According to the source file path, create a new java class file under the java package, paste the code in the source file into the newly created file, modify the relevant code, save and compile.

Find the compiled class file in the target

Find the jar package where the source file is located, right-click and open it in file management.

Unzip the jar package, paste the modified and compiled class file in the target into the corresponding location of the jar package, then repackage it into a zip package and change the suffix to .jar

Comment: Can the source code in the jar package be submitted using git after modification?

When you modify the source code in a JAR package, you actually modify a copy of the JAR package. This modification will not affect the original JAR package, so these modifications cannot be submitted directly using Git.

7.2 When starting the Maven project, the package does not exist and an error message is reported.

If there is no problem with any dependencies, this is usually a project compilation problem. Recompile the project.

Click the M button in Maven, then enter the following command to recompile the project and run it.

mvn idea:idea

7.3 Differences in some sql functions between mysql and Dameng

Only common differences are provided here. Details must be tested according to the modified functions, or refer to official documents.

(1) When creating a table, adding comment comments directly after the column is not supported. Use COMMENT ON IS instead, such as:

COMMENT ON TABLE xxx IS xxx
COMMENT ON COLUMN xxx IS xxx

(2) The date_sub function is not supported, use dateadd(datepart,n,date) instead, where datepart can be: year(yy,yyyy), quarter(qq,q), month(mm,m), dayofyear(dy, y), day(dd,d), week(wk,ww), weekday(dw), hour(hh), minute(mi,n), second(ss,s), millisecond(ms), example:

select dateadd(month, -6, now());
select dateadd(month, 2, now());

(3) The date_format function is not supported. It has three substitution methods:
A: Use datepart instead: Syntax: datepart(datepart, date), returns the specified part representing the date Integer, datepart can be: year(yy,yyyy), quarter(qq,q), month(mm,m), dayofyear(dy,y), day(dd,d), week(wk,ww), weekday( dw), hour(hh), minute(mi,n), second(ss,s), millisecond(ms), example:

select datepart(year, '2023-04-13 08:45:00'); --2023
select datepart(month, '2022-12-13 08:45:00'); --12

B: Use date_part instead. The function is the same as datepart, but the writing method is different. The order of parameters is reversed, and they must be enclosed in quotation marks. Example:

select date_part('2023-12-13 08:45:00', 'year');--2023
select date_part('2022-12-13 08:45:00', 'mm'); -- 12

C: Use extract instead, syntax: extract(dtfield from date), extract the value corresponding to dtfield from the date type date, dtfield can be year, month, day, hour, minute, second, example:

select extract(year from  '2023-12-13 08:45:00'); --2023
select extract(month from  '2022-12-13 08:45:00'); --12

(4) The substring_index function is not supported, use substr / substring instead, syntax:

substr(char[,m[,n]])
substring(char[from m[ for n]])

(5) The group_concat function is not supported, use wm_concat instead, example:

select wm_concat(id) as idstr from persion ORDER BY id ;

(6) The from_unixtime function is not supported, use round instead, syntax:

round(date[,format])

(7) case-when-then-else is not supported, for example:

select case  when id = 2 then "aaa" when id = 3 then "bbb" else "ccc" end as test from (select id from person) tt;

(8) The return value of current_timestamp has time zone, example:

select current_timestamp();
2023-04-37 14:34:18.433839 +08:00

r(yy,yyyy),quarter(qq,q),month(mm,m),dayofyear(dy,y),day(dd,d),week(wk,ww),weekday(dw),hour(hh), minute(mi,n), second(ss,s), millisecond(ms),例子:

select dateadd(month, -6, now());
select dateadd(month, 2, now());

(3) The date_format function is not supported. It has three substitution methods:
A: Use datepart instead: Syntax: datepart(datepart, date), returns the specified part representing the date Integer, datepart can be: year(yy,yyyy), quarter(qq,q), month(mm,m), dayofyear(dy,y), day(dd,d), week(wk,ww), weekday( dw), hour(hh), minute(mi,n), second(ss,s), millisecond(ms), example:

select datepart(year, '2023-04-13 08:45:00'); --2023
select datepart(month, '2022-12-13 08:45:00'); --12

B: Use date_part instead. The function is the same as datepart, but the writing method is different. The order of parameters is reversed, and they must be enclosed in quotation marks. Example:

select date_part('2023-12-13 08:45:00', 'year');--2023
select date_part('2022-12-13 08:45:00', 'mm'); -- 12

C: Use extract instead, syntax: extract(dtfield from date), extract the value corresponding to dtfield from the date type date, dtfield can be year, month, day, hour, minute, second, example:

select extract(year from  '2023-12-13 08:45:00'); --2023
select extract(month from  '2022-12-13 08:45:00'); --12

(4) The substring_index function is not supported, use substr / substring instead, syntax:

substr(char[,m[,n]])
substring(char[from m[ for n]])

(5) The group_concat function is not supported, use wm_concat instead, example:

select wm_concat(id) as idstr from persion ORDER BY id ;

(6) The from_unixtime function is not supported, use round instead, syntax:

round(date[,format])

(7) case-when-then-else is not supported, for example:

select case  when id = 2 then "aaa" when id = 3 then "bbb" else "ccc" end as test from (select id from person) tt;

(8) The return value of current_timestamp has time zone, example:

select current_timestamp();
2023-04-37 14:34:18.433839 +08:00

Guess you like

Origin blog.csdn.net/qq_45925197/article/details/133773383