Activiti7.1.0.M4兼容达梦8数据库
前言
最近在做国产化测试,activiti的服务配置完达梦相关的依赖和连接串后,启动时报错:nested exception is org.activiti.engine.ActivitiException: couldn’t deduct database type from database product name ‘DM DBMS’
原因是:activiti7内置的数据库类型不支持达梦数据库
故而修改activiti的源码对达梦数据库做相关适配
报错分析
activiti源码里并没有兼容达梦数据库,根据报错的位置跟进源码就能找到痕迹:
解决方案
经过以上分析,发现需要修改源码
在jar包中找到相关的文件,拷贝到项目中的相同路径下(一定是相同路径,这样才能在类加载器的加载顺序下覆盖jar中的class),修改代码以做适配。
涉及修改的文件如下:
代码修改
1.ProcessEngineConfigurationImpl类添加成员变量
org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl中添加达梦的成员变量
// 适配达梦数据库
public static final String DATABASE_TYPE_DM = "dm";//达梦
1.1 修改EntityManagerSessionFactory类添加构造方法
这里比较坑,ProcessEngineConfigurationImpl类的源码可能有bug(maybe?),不想管太多,粗暴解决吧。
在org.activiti.engine.impl.variable.EntityManagerSessionFactory中添加构造方法(好像还引入了另一个jar依赖:javax.persistence.javax.persistence-api)
public EntityManagerSessionFactory(EntityManagerFactory entityManagerFactory, boolean handleTransactions, boolean closeEntityManager) {
if (entityManagerFactory == null) {
throw new ActivitiIllegalArgumentException("entityManagerFactory is null");
} else if (!(entityManagerFactory instanceof EntityManagerFactory)) {
throw new ActivitiIllegalArgumentException("EntityManagerFactory must implement 'javax.persistence.EntityManagerFactory'");
} else {
this.entityManagerFactory = (EntityManagerFactory)entityManagerFactory;
this.handleTransactions = handleTransactions;
this.closeEntityManager = closeEntityManager;
}
}
2.ProcessEngineConfigurationImpl类修改方法getDefaultDatabaseTypeMappings()
org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl#getDefaultDatabaseTypeMappings添加达梦的映射
// 适配达梦数据库
databaseTypeMappings.setProperty("DM DBMS", DATABASE_TYPE_DM);
3.DbSqlSessionFactory类修改方法initBulkInsertEnabledMap()
org.activiti.engine.impl.db.DbSqlSessionFactory#initBulkInsertEnabledMap修改判断方法
// 适配达梦数据库
if ("oracle".equals(databaseType) || "dm".equals(databaseType)) {//达梦支持
bulkInsertableMap.put(EventLogEntryEntityImpl.class, Boolean.FALSE);
}
4.AbstractQuery类修改方法addOrder()
org.activiti.engine.impl.AbstractQuery#addOrder修改判断方法
此处为后来者方便,贴了整个方法的代码
// 此处为后来者方便,贴了整个方法的代码
protected void addOrder(String column, String sortOrder, NullHandlingOnOrder nullHandlingOnOrder) {
if (orderBy == null) {
orderBy = "";
} else {
orderBy = orderBy + ", ";
}
String defaultOrderByClause = column + " " + sortOrder;
// 适配达梦数据库
if (nullHandlingOnOrder != null) {
if (nullHandlingOnOrder.equals(NullHandlingOnOrder.NULLS_FIRST)) {
if (ProcessEngineConfigurationImpl.DATABASE_TYPE_H2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_HSQL.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_POSTGRES.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_ORACLE.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_DM.equals(databaseType)) // 适配达梦数据库
{
orderBy = orderBy + defaultOrderByClause + " NULLS FIRST";
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL.equals(databaseType)) {
orderBy = orderBy + "isnull(" + column + ") desc," + defaultOrderByClause;
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_DB2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_MSSQL.equals(databaseType)) {
orderBy = orderBy + "case when " + column + " is null then 0 else 1 end," + defaultOrderByClause;
} else {
orderBy = orderBy + defaultOrderByClause;
}
} else if (nullHandlingOnOrder.equals(NullHandlingOnOrder.NULLS_LAST)) {
if (ProcessEngineConfigurationImpl.DATABASE_TYPE_H2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_HSQL.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_POSTGRES.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_ORACLE.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_DM.equals(databaseType)) // 适配达梦数据库
{
orderBy = orderBy + column + " " + sortOrder + " NULLS LAST";
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_MYSQL.equals(databaseType)) {
orderBy = orderBy + "isnull(" + column + ") asc," + defaultOrderByClause;
} else if (ProcessEngineConfigurationImpl.DATABASE_TYPE_DB2.equals(databaseType)
|| ProcessEngineConfigurationImpl.DATABASE_TYPE_MSSQL.equals(databaseType)) {
orderBy = orderBy + "case when " + column + " is null then 1 else 0 end," + defaultOrderByClause;
} else {
orderBy = orderBy + defaultOrderByClause;
}
}
} else {
orderBy = orderBy + defaultOrderByClause;
}
}
5.ProcessEngineConfigurationImpl类修改方法initSqlSessionFactory()
这一步很重要(参考了不少博主的文章,这一步是其他很多博主忽略了的步骤,自己踩了坑才知道),不然要报:org.activiti.engine.ActivitiException: resource ‘org/activiti/db/create/activiti.dm.create.engine.sql’ is not available
org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl#initSqlSessionFactory添加判断逻辑
if (databaseType != null) {
if (DATABASE_TYPE_DM.equals(databaseType)){
properties.load(getResourceAsStream("org/activiti/db/properties/" + DATABASE_TYPE_ORACLE + ".properties"));
}else {
properties.load(getResourceAsStream("org/activiti/db/properties/" + databaseType + ".properties"));
}
}