activit作为一种轻量级,可嵌入的BPM引擎,广泛应用于企业级管理系统,然而他只支持一些数据库,国产数据库基本不支持,但我们可以扩展
原生支持的数据库:
Activiti数据库类型 | JDBC URL实例 | 备注 |
---|---|---|
h2 | jdbc:h2:tcp://localhost/activiti | 默认配置的数据库 |
mysql | jdbc:mysql://localhost:3306/activiti?autoReconnect=true | 使用mysql-connector-java驱动测试 |
oracle | jdbc:oracle:thin:@localhost:1521:xe | |
postgres | jdbc:postgresql://localhost:5432/activiti | |
db2 | jdbc:db2://localhost:50000/activiti | |
mssql | jdbc:sqlserver://localhost:1433/activiti |
怎么才能支持国产的一些数据库呢,废话不多说,直接上代码。
1、流程引擎扩展配置接口
public interface ActivitiEngineConfigurationConfigurer {
public void configure(SpringProcessEngineConfiguration processEngineConfiguration);
}
扩展实现国产数据库类型可配置
@Component
public class ActivitiEngineConfiguration implements ActivitiEngineConfigurationConfigurer {
//设置数据库类型
@Value(value = "${my.activiti.dbtype}")
private String databaseType;
//设置DbSqlSessionConfigurator
@Autowired
private DbSqlSessionConfigurator dbSqlSessionConfigurator;
@Override
public void configure(SpringProcessEngineConfiguration processEngineConfiguration) {
//设置数据库类型
processEngineConfiguration.setDatabaseType(databaseType);
processEngineConfiguration.setUsingRelationalDatabase(false);
List<ProcessEngineConfigurator> configurators = new ArrayList<ProcessEngineConfigurator>();
configurators.add(dbSqlSessionConfigurator);
processEngineConfiguration.setConfigurators(configurators);
}
}
2、编写ProcessEngineConfigurator,配置SqlSessionFactory
/**
* SqlSessionFactory配置
*/
@Component
public class DbSqlSessionConfigurator implements ProcessEngineConfigurator {
private static final String DEFAULT_MYBATIS_MAPPING_FILE = "config/mapper/mappings.xml";
private static final String DATABASE_GBASE="gbase";
private static final String DATABASE_DM="dameng";
private static final String DATABASE_GAUSSDB100="gaussdb100";
private static final String DATABASE_OSCAR="oscar";
private static Set<String> dbSets=new HashSet<>();
static {
dbSets.add(DATABASE_GBASE);
dbSets.add(DATABASE_DM);
dbSets.add(DATABASE_GAUSSDB100);
dbSets.add(DATABASE_OSCAR);
}
/**此出设置重写的MyDbSqlSessionFactory是为了处理Gbase8s不支持批量插入,其他数据库可不实现该方法*/
@Override
public void beforeInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
//添加重写的SqlSessionFactory
processEngineConfiguration.setDbSqlSessionFactory(new MyDbSqlSessionFactory());
}
//ProcessEngineConfigurationImpl中的configuratorsAfterInit会执行到此处
@Override
public void configure(ProcessEngineConfigurationImpl processEngineConfiguration) {
//创建SqlSessionFactory并设置ProcessEngineConfigurationImpl
processEngineConfiguration.setSqlSessionFactory(createSqlSessionFactory(processEngineConfiguration));
//重新执行initDbSqlSessionFactory
processEngineConfiguration.initDbSqlSessionFactory();
}
private SqlSessionFactory createSqlSessionFactory(ProcessEngineConfigurationImpl processEngineConfiguration) {
InputStream inputStream = null;
try {
//读取的mappings.xm为了处理gbase8s的长字符串类型错误,不是gbase可以加载activiti默认的配置
inputStream = getResourceAsStream(DEFAULT_MYBATIS_MAPPING_FILE);
Environment environment = new Environment("default", processEngineConfiguration.getTransactionFactory(),
processEngineConfiguration.getDataSource());
Reader reader = new InputStreamReader(inputStream);
Properties properties = new Properties();
properties.put("prefix", processEngineConfiguration.getDatabaseTablePrefix());
String wildcardEscapeClause = "";
if ((processEngineConfiguration.getDatabaseWildcardEscapeCharacter() != null)
&& (processEngineConfiguration.getDatabaseWildcardEscapeCharacter().length() != 0)) {
wildcardEscapeClause = " escape '" + processEngineConfiguration.getDatabaseWildcardEscapeCharacter()
+ "'";
}
properties.put("wildcardEscapeClause", wildcardEscapeClause);
// set default properties
properties.put("limitBefore", "");
properties.put("limitAfter", "");
properties.put("limitBetween", "");
properties.put("limitOuterJoinBetween", "");
properties.put("limitBeforeNativeQuery", "");
properties.put("orderBy", "order by ${orderByColumns}");
properties.put("blobType", "BLOB");
properties.put("boolValue", "TRUE");
if (processEngineConfiguration.getDatabaseType() != null) {
//设置读取数据库语法配置文件,文件路径src/main/resource/config/custom/ 自定义的数据类型对应语法文件
if(dbSets.contains(processEngineConfiguration.getDatabaseType().toLowerCase())) {
properties.load(getResourceAsStream("config/custom/"+ processEngineConfiguration.getDatabaseType() + ".properties"));
}else {
properties.load(getResourceAsStream("org/activiti/db/properties/"
+ processEngineConfiguration.getDatabaseType() + ".properties"));
}
}
Configuration configuration = processEngineConfiguration.initMybatisConfiguration(environment, reader,
properties);
return new DefaultSqlSessionFactory(configuration);
} catch (Exception e) {
throw new ActivitiException("Error while building ibatis SqlSessionFactory: " + e.getMessage(), e);
} finally {
IoUtil.closeSilently(inputStream);
}
}
private InputStream getResourceAsStream(String resource) {
return ReflectUtil.getResourceAsStream(resource);
}
@Override
public int getPriority() {
return 0;
}
}
2、重写DbSqlSession的flushInsertEntities方法(适配gbase才需要此步骤)
/**
* SqlSession会话工厂
* 在DbSqlSessionConfigurator(beforeInit方法)中重置会话工厂
*/
public class MyDbSqlSessionFactory extends DbSqlSessionFactory {
@Override
public Session openSession(CommandContext commandContext) {
return new MyDbSqlSession(this, commandContext.getEntityCache());
}
}
public class MyDbSqlSession extends DbSqlSession {
private static final Logger log = LoggerFactory.getLogger(MyDbSqlSession.class);
public MyDbSqlSession(DbSqlSessionFactory dbSqlSessionFactory, EntityCache entityCache) {
super(dbSqlSessionFactory, entityCache);
}
/**
* 重写此方法是为了解决gbase不支持批量插入的问题
* @param entityClass
* @param entitiesToInsert
*/
@Override
protected void flushInsertEntities(Class<? extends Entity> entityClass, Collection<Entity> entitiesToInsert) {
if (entitiesToInsert.size() == 1) {
flushRegularInsert(entitiesToInsert.iterator().next(), entityClass);
}else {
for (Entity entity : entitiesToInsert) {
flushRegularInsert(entity, entityClass);
}
}
}
}
3、装配自定义扩展配置
MyProcessEngineConfiguration cfg = new MyProcessEngineConfiguration();
engineFactory.setProcessEngineConfiguration(cfg);
buildDataSource(cfg);
//判断原生activiti是否支持应用数据库
if(!isSupportDatabase(cfg)){
//国产数据库扩展适配,构建引擎之前
activitiEngineConfigurationConfigurer.configure(cfg);
}
return new Activiti6ProcessEngine(engineFactory.getObject()).setActorStrategyProvider(actorStrategyProvider)
.setUserActionEventHandler(actionEventHandler).setProcessProviders(processProviders)
.setParameterUtils(ParameterUtils).setConditionalExecute(conditionalExecutes);
最后说一句,不按以上方法也可以,可以重写ProcessEngineConfigurationImpl类的相关方法实现。当然,你也可以修改activiti源码,替换jar包,但是那样很不方便也不太合适。