flowable兼容人大金仓
一、添加flowable依赖
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-engine</artifactId>
<version>6.7.2</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring</artifactId>
<version>6.7.2</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-rest</artifactId>
<version>6.7.2</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>4.5.0</version>
</dependency>
这里采用的是flowable6.7.2版本以及liquibase4.5.0版本。
二、修改flowable-engine-common-6.7.2.jar源码
1.下载flowable6.7.2源码 flowable6.7.2源码地址
2.在自己项目下创建org.flowable.common.engine.impl包,然后将源码中对应目录下的AbstractEngineConfiguration类复制到本地项目
3.修改源码,在getDefaultDatabaseTypeMappings方法下添加人大金仓,(因为人大金仓语法支持oracle,这里采用DATABASE_TYPE_KINGBASE = “oracle”)
public static final String DATABASE_TYPE_KINGBASE = "oracle";
public static Properties getDefaultDatabaseTypeMappings() {
Properties databaseTypeMappings = new Properties();
databaseTypeMappings.setProperty("KingbaseES", DATABASE_TYPE_KINGBASE);
三、修改liquibase-core-4.3.5.jar中源码
1.下载liquibase-core-4.3.5.jar源码 liquibase-core-4.3.5源码地址
2.在自己项目下创建liquibase.database.core包,然后将源码中对应目录下的liquibase.database.Database类复制到本地项目,在文件中添加liquibase.database.core.KingBaseDatabase。
3.在该目录在新建KingBaseDatabase类文件,将一下类型复制到该类中
package liquibase.database.core;
import liquibase.CatalogAndSchema;
import liquibase.Scope;
import liquibase.changelog.column.LiquibaseColumn;
import liquibase.database.AbstractJdbcDatabase;
import liquibase.database.DatabaseConnection;
import liquibase.database.ObjectQuotingStrategy;
import liquibase.exception.DatabaseException;
import liquibase.logging.Logger;
import liquibase.statement.SqlStatement;
import liquibase.statement.core.RawCallStatement;
import liquibase.structure.DatabaseObject;
import liquibase.structure.core.Index;
import liquibase.structure.core.Table;
import liquibase.util.StringUtil;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
/**
* 自定义的liquibase kingbase支持,该类基于liquibase4.3.5版本PostgresDatabase修改
* 注意:
* 1、该类与上诉liquibase.database.core.KingBaseDatabase名称一致,否则无法生效
* @autr luoguohua
*/
public class KingBaseDatabase extends AbstractJdbcDatabase {
public static final String PRODUCT_NAME = "KingbaseES";
private static final int KINGBASE_DEFAULT_TCP_PORT_NUMBER = 54321;
private static final Logger LOG = Scope.getCurrentScope().getLog(KingBaseDatabase.class);
private Set<String> systemTablesAndViews = new HashSet<>();
private Set<String> reservedWords = new HashSet<>();
public KingBaseDatabase() {
super.setCurrentDateTimeFunction("NOW()");
// "Reserved" or "reserved (can be function or type)" in PostgreSQL
// from https://www.postgresql.org/docs/9.6/static/sql-keywords-appendix.html
reservedWords.addAll(Arrays.asList("ALL", "ANALYSE", "ANALYZE", "AND", "ANY", "ARRAY", "AS", "ASC",
"ASYMMETRIC", "AUTHORIZATION", "BINARY", "BOTH", "CASE", "CAST", "CHECK", "COLLATE", "COLLATION",
"COLUMN", "CONCURRENTLY", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_CATALOG", "CURRENT_DATE",
"CURRENT_ROLE", "CURRENT_SCHEMA", "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "DEFAULT",
"DEFERRABLE", "DESC", "DISTINCT", "DO", "ELSE", "END", "EXCEPT", "FALSE", "FETCH", "FOR", "FOREIGN",
"FREEZE", "FROM", "FULL", "GRANT", "GROUP", "HAVING", "ILIKE", "IN", "INITIALLY", "INNER", "INTERSECT",
"INTO", "IS", "ISNULL", "JOIN", "LATERAL", "LEADING", "LEFT", "LIKE", "LIMIT", "LOCALTIME",
"LOCALTIMESTAMP", "NATURAL", "NOT", "NOTNULL", "NULL", "OFFSET", "ON", "ONLY", "OR", "ORDER", "OUTER",
"OVERLAPS", "PLACING", "PRIMARY", "REFERENCES", "RETURNING", "RIGHT", "SELECT", "SESSION_USER",
"SIMILAR", "SOME", "SYMMETRIC", "TABLE", "TABLESAMPLE", "THEN", "TO", "TRAILING", "TRUE", "UNION",
"UNIQUE", "USER", "USING", "VARIADIC", "VERBOSE", "WHEN", "WHERE", "WINDOW", "WITH"));
super.sequenceNextValueFunction = "nextval('%s')";
super.sequenceCurrentValueFunction = "currval('%s')";
super.unmodifiableDataTypes.addAll(Arrays.asList("bool", "int4", "int8", "float4", "float8", "bigserial", "serial", "oid", "bytea", "date", "timestamptz", "text"));
super.unquotedObjectsAreUppercased=false;
}
@Override
public boolean equals(Object o) {
// Actually, we don't need and more specific checks than the base method. This exists just to make SONAR happy.
return super.equals(o);
}
@Override
public int hashCode() {
// Actually, we don't need and more specific hashing than the base method. This exists just to make SONAR happy.
return super.hashCode();
}
@Override
public Set<String> getSystemViews() {
return systemTablesAndViews;
}
@Override
protected String getDefaultDatabaseProductName() {
return PRODUCT_NAME;
}
@Override // 该方法判断是否为liquibase实现的database
public boolean isCorrectDatabaseImplementation(DatabaseConnection conn) throws DatabaseException {
return PRODUCT_NAME.equalsIgnoreCase(conn.getDatabaseProductName());
}
@Override
public String getDefaultDriver(String url) {
if (url.startsWith("jdbc:kingbase8:")) {
return "com.kingbase8.Driver";
}
return null;
}
@Override
public String getShortName() {
return "kingbase";
}
@Override
public Integer getDefaultPort() {
return KINGBASE_DEFAULT_TCP_PORT_NUMBER;
}
@Override
public boolean supportsInitiallyDeferrableColumns() {
return false;
}
@Override
public boolean supportsTablespaces() {
return false;
}
@Override
public int getPriority() {
return PRIORITY_DEFAULT;
}
@Override
public boolean supportsCatalogInObjectName(Class<? extends DatabaseObject> type) {
return false;
}
@Override
public boolean supportsSequences() {
return true;
}
@Override
public String getDatabaseChangeLogTableName() {
return super.getDatabaseChangeLogTableName().toLowerCase(Locale.US);
}
@Override
public String getDatabaseChangeLogLockTableName() {
return super.getDatabaseChangeLogLockTableName().toLowerCase(Locale.US);
}
@Override
public void setConnection(DatabaseConnection conn) {
super.setConnection(conn);
}
@Override
public boolean isSystemObject(DatabaseObject example) {
// All tables in the schemas pg_catalog and pg_toast are definitely system tables.
if
(
(example instanceof Table)
&& (example.getSchema() != null)
&& (
("SYS_CATALOG".equals(example.getSchema().getName()))
|| ("SYS_TOAST".equals(example.getSchema().getName()))
)
) {
return true;
}
return super.isSystemObject(example);
}
@Override
public String getAutoIncrementClause() {
return "";
}
@Override
public boolean generateAutoIncrementStartWith(BigInteger startWith) {
return false;
}
@Override
public boolean generateAutoIncrementBy(BigInteger incrementBy) {
return false;
}
@Override
public String escapeIndexName(final String catalogName, final String schemaName, final String indexName) {
return escapeObjectName(catalogName, schemaName, indexName, Index.class).toUpperCase().replace("PUBLIC.","");
}
@Override
public String escapeObjectName(String objectName, Class<? extends DatabaseObject> objectType) {
if ((quotingStrategy == ObjectQuotingStrategy.LEGACY) && hasMixedCase(objectName)) {
return "\"" + objectName + "\"";
} else if (objectType != null && LiquibaseColumn.class.isAssignableFrom(objectType)) {
return (objectName != null && !objectName.isEmpty()) ? objectName.trim() : objectName;
}
return super.escapeObjectName(objectName, objectType);
}
@Override
public String correctObjectName(String objectName, Class<? extends DatabaseObject> objectType) {
if ((objectName == null) || (quotingStrategy != ObjectQuotingStrategy.LEGACY)) {
return super.correctObjectName(objectName, objectType);
}
if (objectName.contains("-")
|| hasMixedCase(objectName)
|| startsWithNumeric(objectName)
|| isReservedWord(objectName)) {
return objectName;
} else {
return objectName.toLowerCase(Locale.US);
}
}
protected boolean hasMixedCase(String tableName) {
if (tableName == null) {
return false;
}
return StringUtil.hasUpperCase(tableName) && StringUtil.hasLowerCase(tableName);
}
@Override
public boolean isReservedWord(String tableName) {
return reservedWords.contains(tableName.toUpperCase());
}
@Override
protected SqlStatement getConnectionSchemaNameCallStatement() {
return new RawCallStatement("select current_schema()");
}
@Override
public String generatePrimaryKeyName(final String tableName) {
return tableName.toUpperCase(Locale.US) + "_PKEY";
}
@Override
public CatalogAndSchema.CatalogAndSchemaCase getSchemaAndCatalogCase() {
return CatalogAndSchema.CatalogAndSchemaCase.LOWER_CASE;
}
}
三、替换相应的源码
将项目打包后,生成的对应class对maven包中的依赖进行相应的覆盖。
四、可能出现的问题
1.public.flw_ev_databasechangeloglock建表失败,在项目启动时会自动建表,这个表建表失败,由于项目时间问题未排查,进行手动建表
CREATE TABLE public.flw_ev_databasechangeloglock (ID INT NOT NULL,
LOCKED BOOLEAN NOT NULL, LOCKGRANTED TIMESTAMP WITHOUT TIME ZONE, LOCKEDBY VARCHAR(255),
CONSTRAINT FLW_EV_DATABASECHANGELOGLOCK_PKEY PRIMARY KEY (ID))
2.找不到flowable.common.app.idm-admin…
yml文件添加相关配置
flowable:
# 自动部署验证设置:true-开启(默认)、false-关闭
# check-process-definitions: false
#配置项可以设置流程引擎启动和关闭时数据库执行的策略
# database-schema-update: false
#保存历史数据级别设置为full最高级别,便于历史数据的追溯
# history-level: full
#启动定时任务JOB
async-executor-activate: true
#该配置只是防止报错,没有实际意义
common:
app:
idm-admin:
password: test
user: test
#没有实际意义
idm-url: http://localhost:8080/flowable-demo
总结
这种采用的是spring依赖方式,未采用springboot。这种方式启动成功后会建立47张相关的表