近期因项目需要,要适配flowable到国产数据库TiDB,将碰到的问题做个记录,虽然问题暂时解决了,但不是最优解,如有更好的配置方法,烦请指教!
版本
flowable:6.4.2版本
tidb:7.5版本
问题描述
由于tidb完全兼容mysql,所以系统连接和mysql一致,本来以为不用做任何修改,将mysql导入到tidb后本地windows环境直接启动系统发现正常,但部署到linux服务器后无法正常启动,报如下错误:
FlowableWrongDbException: version mismatch: library version is ‘6.5.0.1‘, db version is 5.99.0.0
解决思路
由于这个错在以前连接mysql时碰到过,当时的原因是mysql大小写敏感问题导致的,需要配置lower_case_table_names参数,所以这边猜测也是这个原因,于是看了tidb官方文档,描述如下:
tidb对lower_case_table_names 参数为2的描述是 :
表名存储为给定的大小写但是比较的时候是小写的。
这边尝试将lower_case_table_names参数的值设置成1,没报错,但还是没效果,没办法,这边只能调试flowable源码,最后发现是 isTablePresent 这个方法没有找不到表名:
public boolean isTablePresent(String tableName) {
// ACT-1610: in case the prefix IS the schema itself, we don't add the
// prefix, since the check is already aware of the schema
DbSqlSession dbSqlSession = getDbSqlSession();
DbSqlSessionFactory dbSqlSessionFactory = dbSqlSession.getDbSqlSessionFactory();
if (!dbSqlSession.getDbSqlSessionFactory().isTablePrefixIsSchema()) {
tableName = prependDatabaseTablePrefix(tableName);
}
Connection connection = null;
try {
connection = dbSqlSession.getSqlSession().getConnection();
DatabaseMetaData databaseMetaData = connection.getMetaData();
ResultSet tables = null;
String catalog = dbSqlSession.getConnectionMetadataDefaultCatalog();
if (dbSqlSessionFactory.getDatabaseCatalog() != null && dbSqlSessionFactory.getDatabaseCatalog().length() > 0) {
catalog = dbSqlSessionFactory.getDatabaseCatalog();
}
String schema = dbSqlSession.getConnectionMetadataDefaultSchema();
if (dbSqlSessionFactory.getDatabaseSchema() != null && dbSqlSessionFactory.getDatabaseSchema().length() > 0) {
schema = dbSqlSessionFactory.getDatabaseSchema();
} else if (dbSqlSessionFactory.isTablePrefixIsSchema() && StringUtils.isNotEmpty(dbSqlSessionFactory.getDatabaseTablePrefix())) {
schema = dbSqlSessionFactory.getDatabaseTablePrefix();
if (StringUtils.isNotEmpty(schema) && schema.endsWith(".")) {
schema = schema.substring(0, schema.length() - 1);
}
}
String databaseType = dbSqlSessionFactory.getDatabaseType();
if ("postgres".equals(databaseType)) {
tableName = tableName.toLowerCase();
} else if ("cockroachdb".equals(databaseType)) {
tableName = tableName.toLowerCase(); // same as postgres
schema = "public"; // CRDB only supports public right now
}
if (schema != null && "oracle".equals(databaseType)) {
schema = schema.toUpperCase();
}
if (catalog != null && catalog.length() == 0) {
catalog = null;
}
try {
//分别在控制台打印出catalog, schema, tableName的值
// System.out.println("catalog: " + catalog);
// System.out.println("schema: " + schema);
// System.out.println("tableName: " + tableName);
tables = databaseMetaData.getTables(catalog, schema, tableName, JDBC_METADATA_TABLE_TYPES);
return tables.next();
} finally {
try {
if (tables != null) {
tables.close();
}
} catch (Exception e) {
logger.error("Error closing meta data tables", e);
}
}
} catch (Exception e) {
throw new FlowableException("couldn't check if tables are already present using metadata: " + e.getMessage(), e);
}
}
以上方法是flowable检查是否存在物理表的方法,最终定位到是以下方法没有获取到表名:
这边增加日志后,打印输出如下:
flowable对以上3张表做了验证,并且验证后直接报错。
由于这几张物理表建表时是用的小写,我怀疑可能是这的问题,于是这边把act_de_property,act_id_property,act_hi_procinst,act_ru_execution这几张表删除后用大写的表名重建后再重启服务发现正常。
总结
tidb官网说明是 lower_case_table_names 不区分windows和linux,但实际还是有区别,我理解是windows下默认还是大小写不敏感,但linux下还是大小写敏感导致的,不然也不会出现本地windows环境正常,而部署到linux无法启动。
如有其他解决办法,欢迎留言!