Flowable6.8适配人大金仓 达梦
目录
4.1 在项目中新建liquibase.database.core 包
前言
由于Flowable 工作流框架只支持h2,mysql,oracle,postgres,db2 sql server 数据库,不支持国产数据库,所以本文介绍下Flowable6.8.0版本适配人大金仓(KingbaseES V008R006C008B0014),达梦数据库教程
一、Flowable6.8 适配人大金仓
1.引入postgreSQL依赖
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.9</version>
</dependency>
2.配置驱动
虽然用的是人大金仓数据库,但是可以使用postgresql 的数据驱动,ip+端口和数据库名称还是人大金仓的。参考:2. 概述 — KingbaseES产品手册https://help.kingbase.com.cn/v8/development/client-interfaces-frame/activiti/activiti-1.html
spring:
datasource:
username: kingbase
password: 123456
url: jdbc:postgresql://192.168.124.8:4321/flowable6?useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true
driver-class-name: org.postgresql.Driver
3.资料
docker 安装 kingbase
这里只介绍了对于数据库的改动,springboot 整合 flowable 是默认已经完成了,然后进行的国产数据库适配。下面链接是demo
启动完成访问:http://localhost:7080/? 即可。
二,Flowable 6.8 适配DMV8
达梦版本信息:
BANNER???????? | ID_CODE |
DM Database Server 64 V8 | --03134284058-20230726-197096-20046 Pack4 |
DB Version: 0x7000c? | --03134284058-20230726-197096-20046 Pack4 ? |
03134284058-20230726-197096-20046 | --03134284058-20230726-197096-20046 Pack4 |
? 1.引入达梦依赖
?
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver18</artifactId>
<version>8.1.2.141</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
2.配置数据库
这里并不需要配置数据库名称哟!
server:
port: 7081
spring:
datasource:
username: SYSDBA
password: SYSDBA001
#compatibleMode=oracle 是用来设置兼容oracle 的
url: jdbc:dm://192.168.124.8:30236?compatibleMode=oracle
driver-class-name: dm.jdbc.driver.DmDriver
type: com.alibaba.druid.pool.DruidDataSource
flowable:
async-executor-activate: false
database-schema-update: true
3.确认liquibase的版本
方法一:可以在idea 右侧 maven 处找到liquibase 的版本,这需要你大概知道liquibase 在谁的包下,不然不好找。
方法二:通过左侧项目的External Libraries 文件夹里查找org.liquibae?
可以得知,我的liquibase 版本是4.9.1 。liquibase3.x 和 liquibase4.x 的适配步骤是不一样的,我这篇文章就介绍liquibase4.x 的适配步骤,liquibase3.x 可以通过下面的参考链接查询。
4.liquibase4.x的适配步骤
4.1 在项目中新建liquibase.database.core 包
4.2 创建OracleDatabase,并复制下面代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package liquibase.database.core;
import java.lang.reflect.Method;
import java.sql.*;
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.ResourceBundle;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import dm.jdbc.driver.DmdbConnection;
import liquibase.CatalogAndSchema;
import liquibase.GlobalConfiguration;
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.UniqueConstraint;
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.JdbcUtil;
import liquibase.util.StringUtil;
public class OracleDatabase extends AbstractJdbcDatabase {
public static final Pattern PROXY_USER = Pattern.compile(".*(?:thin|oci)\\:(.+)/@.*");
public static final String PRODUCT_NAME = "oracle";
private static ResourceBundle coreBundle = ResourceBundle.getBundle("liquibase/i18n/liquibase-core");
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;
public OracleDatabase() {
super.unquotedObjectsAreUppercased = true;
super.setCurrentDateTimeFunction("SYSTIMESTAMP");
this.dateFunctions.add(new DatabaseFunction("SYSDATE"));
this.dateFunctions.add(new DatabaseFunction("SYSTIMESTAMP"));
this.dateFunctions.add(new DatabaseFunction("CURRENT_TIMESTAMP"));
super.sequenceNextValueFunction = "%s.nextval";
super.sequenceCurrentValueFunction = "%s.currval";
}
@Override
public int getPriority() {
return 1;
}
private void tryProxySession(String url, Connection con) {
Matcher m = PROXY_USER.matcher(url);
if (m.matches()) {
Properties props = new Properties();
props.put("PROXY_USER_NAME", m.group(1));
Method method;
try {
method = con.getClass().getMethod("openProxySession", Integer.TYPE, Properties.class);
method.setAccessible(true);
method.invoke(con, 1, props);
} catch (Exception var8) {
Scope.getCurrentScope().getLog(this.getClass()).info("Could not open proxy session on OracleDatabase: " + var8.getCause().getMessage());
return;
}
try {
method = con.getClass().getMethod("isProxySession");
method.setAccessible(true);
boolean b = (Boolean)method.invoke(con);
if (!b) {
Scope.getCurrentScope().getLog(this.getClass()).info("Proxy session not established on OracleDatabase: ");
}
} catch (Exception var7) {
Scope.getCurrentScope().getLog(this.getClass()).info("Could not open proxy session on OracleDatabase: " + var7.getCause().getMessage());
}
}
}
@Override
public void setConnection(DatabaseConnection conn) {
this.reservedWords.addAll(Arrays.asList("GROUP", "USER", "SESSION", "PASSWORD", "RESOURCE", "START", "SIZE", "UID", "DESC", "ORDER"));
Connection sqlConn = null;
if (!(conn instanceof OfflineConnection)) {
try {
if (conn instanceof JdbcConnection) {
sqlConn = ((JdbcConnection)conn).getWrappedConnection();
}
} catch (Exception var29) {
throw new UnexpectedLiquibaseException(var29);
}
if (sqlConn != null) {
this.tryProxySession(conn.getURL(), sqlConn);
try {
this.reservedWords.addAll(Arrays.asList(sqlConn.getMetaData().getSQLKeywords().toUpperCase().split(",\\s*")));
} catch (SQLException var28) {
Scope.getCurrentScope().getLog(this.getClass()).info("Could get sql keywords on OracleDatabase: " + var28.getMessage());
}
try {
Method method = sqlConn.getClass().getMethod("setRemarksReporting", Boolean.TYPE);
method.setAccessible(true);
method.invoke(sqlConn, true);
} catch (Exception var27) {
Scope.getCurrentScope().getLog(this.getClass()).info("Could not set remarks reporting on OracleDatabase: " + var27.getMessage());
}
/**
CallableStatement statement = null;
String sql;
try {
statement = sqlConn.prepareCall("{call DBMS_UTILITY.DB_VERSION(?,?)}");
statement.registerOutParameter(1, 12);
statement.registerOutParameter(2, 12);
statement.execute();
String compatibleVersion = statement.getString(2);
if (compatibleVersion != null) {
Matcher majorVersionMatcher = Pattern.compile("(\\d+)\\.(\\d+)\\..*").matcher(compatibleVersion);
if (majorVersionMatcher.matches()) {
this.databaseMajorVersion = Integer.valueOf(majorVersionMatcher.group(1));
this.databaseMinorVersion = Integer.valueOf(majorVersionMatcher.group(2));
}
}
} catch (SQLException var25) {
sql = "Cannot read from DBMS_UTILITY.DB_VERSION: " + var25.getMessage();
Scope.getCurrentScope().getLog(this.getClass()).info("Could not set check compatibility mode on OracleDatabase, assuming not running in any sort of compatibility mode: " + sql);
} finally {
JdbcUtil.closeStatement(statement);
} */
//-----------------------------------修改内容-------------------------------
CallableStatement statement = null;
String sql;
try {
DatabaseMetaData metaData = sqlConn.getMetaData();
Connection connection = metaData.getConnection();
if (connection instanceof DmdbConnection) {
String compatibleVersion = "11.2.0.4.0";
Matcher majorVersionMatcher = Pattern.compile("(\\d+)\\.(\\d+)\\..*").matcher(compatibleVersion);
if (majorVersionMatcher.matches()) {
this.databaseMajorVersion = Integer.valueOf(majorVersionMatcher.group(1));
this.databaseMinorVersion = Integer.valueOf(majorVersionMatcher.group(2));
}
}else{
//noinspection HardCodedStringLiteral
statement = sqlConn.prepareCall("{call DBMS_UTILITY.DB_VERSION(?,?)}");
statement.registerOutParameter(1, Types.VARCHAR);
statement.registerOutParameter(2, Types.VARCHAR);
statement.execute();
String compatibleVersion = statement.getString(2); //"11.2.0.4.0";
if (compatibleVersion != null) {
Matcher majorVersionMatcher = Pattern.compile("(\\d+)\\.(\\d+)\\..*").matcher(compatibleVersion);
if (majorVersionMatcher.matches()) {
this.databaseMajorVersion = Integer.valueOf(majorVersionMatcher.group(1));
this.databaseMinorVersion = Integer.valueOf(majorVersionMatcher.group(2));
}
}
}
} catch (SQLException e) {
@SuppressWarnings("HardCodedStringLiteral") String message = "Cannot read from DBMS_UTILITY.DB_VERSION: " + e.getMessage();
//noinspection HardCodedStringLiteral
Scope.getCurrentScope().getLog(getClass()).info("Could not set check compatibility mode on OracleDatabase, assuming not running in any sort of compatibility mode: " + message);
} finally {
JdbcUtil.closeStatement(statement);
}
//-----------------------------------修改内容-------------------------------
if (GlobalConfiguration.DDL_LOCK_TIMEOUT.getCurrentValue() != null) {
int timeoutValue = (Integer)GlobalConfiguration.DDL_LOCK_TIMEOUT.getCurrentValue();
Scope.getCurrentScope().getLog(this.getClass()).fine("Setting DDL_LOCK_TIMEOUT value to " + timeoutValue);
sql = "ALTER SESSION SET DDL_LOCK_TIMEOUT=" + timeoutValue;
PreparedStatement ddlLockTimeoutStatement = null;
try {
ddlLockTimeoutStatement = sqlConn.prepareStatement(sql);
ddlLockTimeoutStatement.execute();
} catch (SQLException var23) {
Scope.getCurrentScope().getUI().sendErrorMessage("Unable to set the DDL_LOCK_TIMEOUT_VALUE: " + var23.getMessage(), var23);
Scope.getCurrentScope().getLog(this.getClass()).warning("Unable to set the DDL_LOCK_TIMEOUT_VALUE: " + var23.getMessage(), var23);
} finally {
JdbcUtil.closeStatement(ddlLockTimeoutStatement);
}
}
}
}
super.setConnection(conn);
}
@Override
public String getShortName() {
return "oracle";
}
@Override
protected String getDefaultDatabaseProductName() {
return "Oracle";
}
@Override
public int getDatabaseMajorVersion() throws DatabaseException {
return this.databaseMajorVersion == null ? super.getDatabaseMajorVersion() : this.databaseMajorVersion;
}
@Override
public int getDatabaseMinorVersion() throws DatabaseException {
return this.databaseMinorVersion == null ? super.getDatabaseMinorVersion() : this.databaseMinorVersion;
}
@Override
public Integer getDefaultPort() {
return 1521;
}
@Override
public String getJdbcCatalogName(CatalogAndSchema schema) {
return null;
}
@Override
public String getJdbcSchemaName(CatalogAndSchema schema) {
return this.correctObjectName(schema.getCatalogName() == null ? schema.getSchemaName() : schema.getCatalogName(), Schema.class);
}
@Override
protected String getAutoIncrementClause(String generationType, Boolean defaultOnNull) {
if (StringUtil.isEmpty(generationType)) {
return super.getAutoIncrementClause();
} else {
String autoIncrementClause = "GENERATED %s AS IDENTITY";
String generationStrategy = generationType;
if (Boolean.TRUE.equals(defaultOnNull) && generationType.toUpperCase().equals("BY DEFAULT")) {
generationStrategy = generationType + " ON NULL";
}
return String.format(autoIncrementClause, generationStrategy);
}
}
@Override
public String generatePrimaryKeyName(String tableName) {
return tableName.length() > 27 ? "PK_" + tableName.toUpperCase(Locale.US).substring(0, 27) : "PK_" + tableName.toUpperCase(Locale.US);
}
@Override
public boolean supportsInitiallyDeferrableColumns() {
return true;
}
@Override
public boolean isReservedWord(String objectName) {
return this.reservedWords.contains(objectName.toUpperCase());
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public boolean supportsSchemas() {
return false;
}
@Override
protected String getConnectionCatalogName() throws DatabaseException {
if (this.getConnection() instanceof OfflineConnection) {
return this.getConnection().getCatalog();
} else if (!(this.getConnection() instanceof JdbcConnection)) {
return this.defaultCatalogName;
} else {
try {
return (String)((ExecutorService)Scope.getCurrentScope().getSingleton(ExecutorService.class)).getExecutor("jdbc", this).queryForObject(new RawCallStatement("select sys_context( 'userenv', 'current_schema' ) from dual"), String.class);
} catch (Exception var2) {
Scope.getCurrentScope().getLog(this.getClass()).info("Error getting default schema", var2);
return null;
}
}
}
@Override
public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
return "oracle".equalsIgnoreCase(conn.getDatabaseProductName());
}
@Override
public String getDefaultDriver(String url) {
return url.startsWith("jdbc:oracle") ? "oracle.jdbc.OracleDriver" : null;
}
@Override
public String getDefaultCatalogName() {
return super.getDefaultCatalogName() == null ? null : super.getDefaultCatalogName().toUpperCase(Locale.US);
}
@Override
public String getDateLiteral(String isoDate) {
String normalLiteral = super.getDateLiteral(isoDate);
if (this.isDateOnly(isoDate)) {
return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD')";
} else if (this.isTimeOnly(isoDate)) {
return "TO_DATE(" + normalLiteral + ", 'HH24:MI:SS')";
} else if (this.isTimestamp(isoDate)) {
return "TO_TIMESTAMP(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS.FF')";
} else if (this.isDateTime(isoDate)) {
int seppos = normalLiteral.lastIndexOf(46);
if (seppos != -1) {
normalLiteral = normalLiteral.substring(0, seppos) + "'";
}
return "TO_DATE(" + normalLiteral + ", 'YYYY-MM-DD HH24:MI:SS')";
} else {
return "UNSUPPORTED:" + isoDate;
}
}
@Override
public boolean isSystemObject(DatabaseObject example) {
if (example == null) {
return false;
} else if (this.isLiquibaseObject(example)) {
return false;
} else {
if (example instanceof Schema) {
label131: {
if (!"SYSTEM".equals(example.getName()) && !"SYS".equals(example.getName()) && !"CTXSYS".equals(example.getName()) && !"XDB".equals(example.getName())) {
if (!"SYSTEM".equals(example.getSchema().getCatalogName()) && !"SYS".equals(example.getSchema().getCatalogName()) && !"CTXSYS".equals(example.getSchema().getCatalogName()) && !"XDB".equals(example.getSchema().getCatalogName())) {
break label131;
}
return true;
}
return true;
}
} else if (this.isSystemObject(example.getSchema())) {
return true;
}
if (example instanceof Catalog) {
if ("SYSTEM".equals(example.getName()) || "SYS".equals(example.getName()) || "CTXSYS".equals(example.getName()) || "XDB".equals(example.getName())) {
return true;
}
} else if (example.getName() != null) {
if (example.getName().startsWith("BIN$")) {
boolean filteredInOriginalQuery = this.canAccessDbaRecycleBin();
if (!filteredInOriginalQuery) {
filteredInOriginalQuery = StringUtil.trimToEmpty(example.getSchema().getName()).equalsIgnoreCase(this.getConnection().getConnectionUserName());
}
if (!filteredInOriginalQuery) {
return true;
}
return !(example instanceof PrimaryKey) && !(example instanceof Index) && !(example instanceof UniqueConstraint);
}
if (example.getName().startsWith("AQ$")) {
return true;
}
if (example.getName().startsWith("DR$")) {
return true;
}
if (example.getName().startsWith("SYS_IOT_OVER")) {
return true;
}
if ((example.getName().startsWith("MDRT_") || example.getName().startsWith("MDRS_")) && example.getName().endsWith("$")) {
return true;
}
if (example.getName().startsWith("MLOG$_")) {
return true;
}
if (example.getName().startsWith("RUPD$_")) {
return true;
}
if (example.getName().startsWith("WM$_")) {
return true;
}
if ("CREATE$JAVA$LOB$TABLE".equals(example.getName())) {
return true;
}
if ("JAVA$CLASS$MD5$TABLE".equals(example.getName())) {
return true;
}
if (example.getName().startsWith("ISEQ$$_")) {
return true;
}
if (example.getName().startsWith("USLOG$")) {
return true;
}
if (example.getName().startsWith("SYS_FBA")) {
return true;
}
}
return super.isSystemObject(example);
}
}
@Override
public boolean supportsTablespaces() {
return true;
}
@Override
public boolean supportsAutoIncrement() {
boolean isAutoIncrementSupported = false;
try {
if (this.getDatabaseMajorVersion() >= 12) {
isAutoIncrementSupported = true;
}
} catch (DatabaseException var3) {
isAutoIncrementSupported = false;
}
return isAutoIncrementSupported;
}
@Override
public boolean supportsRestrictForeignKeys() {
return false;
}
@Override
public int getDataTypeMaxParameters(String dataTypeName) {
if ("BINARY_FLOAT".equals(dataTypeName.toUpperCase())) {
return 0;
} else {
return "BINARY_DOUBLE".equals(dataTypeName.toUpperCase()) ? 0 : super.getDataTypeMaxParameters(dataTypeName);
}
}
public String getSystemTableWhereClause(String tableNameColumn) {
List<String> clauses = new ArrayList(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 '" + (String)clauses.get(i) + "%'");
}
return "(" + StringUtil.join(clauses, " AND ") + ")";
}
@Override
public boolean jdbcCallsCatalogsSchemas() {
return true;
}
public Set<String> getUserDefinedTypes() {
if (this.userDefinedTypes == null) {
this.userDefinedTypes = new HashSet();
if (this.getConnection() != null && !(this.getConnection() instanceof OfflineConnection)) {
try {
try {
this.userDefinedTypes.addAll(((ExecutorService)Scope.getCurrentScope().getSingleton(ExecutorService.class)).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT DISTINCT TYPE_NAME FROM ALL_TYPES"), String.class));
} catch (DatabaseException var2) {
this.userDefinedTypes.addAll(((ExecutorService)Scope.getCurrentScope().getSingleton(ExecutorService.class)).getExecutor("jdbc", this).queryForList(new RawSqlStatement("SELECT TYPE_NAME FROM USER_TYPES"), String.class));
}
} catch (DatabaseException var3) {
}
}
}
return this.userDefinedTypes;
}
@Override
public String generateDatabaseFunctionValue(DatabaseFunction databaseFunction) {
if (databaseFunction != null && "current_timestamp".equalsIgnoreCase(databaseFunction.toString())) {
return databaseFunction.toString();
} else if (!(databaseFunction instanceof SequenceNextValueFunction) && !(databaseFunction instanceof SequenceCurrentValueFunction)) {
return super.generateDatabaseFunctionValue(databaseFunction);
} else {
String quotedSeq = super.generateDatabaseFunctionValue(databaseFunction);
return quotedSeq.replaceFirst("\"([^.\"]+)\\.([^.\"]+)\"", "\"$1\".\"$2\"");
}
}
@Override
public ValidationErrors validate() {
ValidationErrors errors = super.validate();
DatabaseConnection connection = this.getConnection();
if (connection != null && !(connection instanceof OfflineConnection)) {
if (!this.canAccessDbaRecycleBin()) {
errors.addWarning(this.getDbaRecycleBinWarning());
}
return errors;
} else {
Scope.getCurrentScope().getLog(this.getClass()).info("Cannot validate offline database");
return errors;
}
}
public String getDbaRecycleBinWarning() {
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\nThe user you used to connect to the database (" + this.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 " + this.getConnection().getConnectionUserName() + ";";
}
public boolean canAccessDbaRecycleBin() {
if (this.canAccessDbaRecycleBin == null) {
DatabaseConnection connection = this.getConnection();
if (connection == null || connection instanceof OfflineConnection) {
return false;
}
Statement statement = null;
try {
statement = ((JdbcConnection)connection).createStatement();
ResultSet resultSet = statement.executeQuery("select 1 from dba_recyclebin where 0=1");
resultSet.close();
this.canAccessDbaRecycleBin = true;
} catch (Exception var7) {
if (var7 instanceof SQLException && var7.getMessage().startsWith("ORA-00942")) {
this.canAccessDbaRecycleBin = false;
} else {
Scope.getCurrentScope().getLog(this.getClass()).warning("Cannot check dba_recyclebin access", var7);
this.canAccessDbaRecycleBin = false;
}
} finally {
JdbcUtil.close((ResultSet)null, statement);
}
}
return this.canAccessDbaRecycleBin;
}
@Override
public boolean supportsNotNullConstraintNames() {
return true;
}
public boolean isValidOracleIdentifier(String identifier, Class<? extends DatabaseObject> type) {
if (identifier != null && identifier.length() >= 1) {
if (!identifier.matches("^(i?)[A-Z][A-Z0-9\\$\\_\\#]*$")) {
return false;
} else {
return identifier.length() <= 128;
}
} else {
return false;
}
}
public int getIdentifierMaximumLength() {
try {
if (this.getDatabaseMajorVersion() < 12) {
return 30;
} else {
return this.getDatabaseMajorVersion() == 12 && this.getDatabaseMinorVersion() <= 1 ? 30 : 128;
}
} catch (DatabaseException var2) {
throw new UnexpectedLiquibaseException("Cannot determine the Oracle database version number", var2);
}
}
}
然后重启项目即可。没有报错,查看达梦数据库?
?
5.资料
flowable 6.8 适配达梦V8 Demo 下载链接:
【免费】flowable6.8适配达梦数据库资源-CSDN文库https://download.csdn.net/download/qq_41169544/88706720
?docker 达梦安装
docker DM 达梦-CSDN博客https://blog.csdn.net/qq_41169544/article/details/135401772
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!