开源流程引擎Camunda BPM如何扩展数据库表
2021/6/21 19:28:34
本文主要是介绍开源流程引擎Camunda BPM如何扩展数据库表,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
前言
在使用开源流程引擎(如:JBPM、Activiti、Flowable、Camunda等)的时候,经常会遇到这样的需求,我们需要按照业务需求增加一张数据库的表,而且这张表是跟工作流引擎有交互的(注意不是一张业务表),那么如何扩展一张数据库表并无缝地融入到流程引擎的机制中呢?下面以Camunda BPM为例,介绍如何扩展自定义数据库表。
模拟一个客户需求
假设某一客户的业务流程很多,有几百个,这些流程在camunda里是平层放的,没有按照业务归类,不便于管理和使用,客户希望把这些流程按照业务分类展示,就像一棵目录树,分A、B、C一层目录,A下面又分A1、A2、A3第二层目录,A1、A2、A3下面放的是具体的业务流程定义。
我们分析这个需求,需要扩展一张数据库表记录业务分类目录,同时需要在流程定义表里扩展一个字段,关联这个业务分类目录,这样才能实现流程定义按照业务分类展示。
扩展数据库表步骤
1. 建表
在camunda数据库里创建一张表,命名为act_re_proc_catalog(流程分类目录表)。
MySQL建表语句:
CREATE TABLE `act_re_proc_catalog` ( `ID_` varchar(64) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '主键', `CATALOG_CODE_` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '业务分类编码', `CATALOG_NAME_` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '业务分类名称', `PARENT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '父节点ID', `CREATE_TIME_` datetime DEFAULT NULL COMMENT '插入或修改时间', `TENANT_ID_` varchar(64) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`ID_`) USING BTREE, KEY `ACT_IDX_PROC_CATALOG_TENANT_ID` (`TENANT_ID_`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=COMPACT;
2. 创建实体类
按照camunda的规则,创建实体类必须基于接口,所以先创建接口,接口命名为ProcessCatalog。
import java.util.Date; public interface ProcessCatalog { String getId(); String getCatalogCode() ; String getCatalogName() ; String getParentId() ; Date getCreateTime() ; String getTenantId(); }
接着创建实体类,实现上面的接口和DbEntity接口,实体类命名为ProcessCatalogEntity。
import org.camunda.bpm.engine.impl.db.DbEntity; import org.camunda.bpm.engine.repository.ProcessCatalog; import java.io.Serializable; import java.util.Date; /** * 流程目录实体类 */ public class ProcessCatalogEntity implements Serializable, ProcessCatalog, DbEntity { private static final long serialVersionUID = 1L; protected String id; protected String catalogCode; protected String catalogName; protected String parentId; protected Date createTime; protected String tenantId; public Object getPersistentState() { // properties of this entity are immutable // so always the same value is returned // so never will an update be issued for a DeploymentEntity return ProcessCatalogEntity.class; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCatalogCode() { return catalogCode; } public void setCatalogCode(String catalogCode) { this.catalogCode = catalogCode; } public String getCatalogName() { return catalogName; } public void setCatalogName(String catalogName) { this.catalogName = catalogName; } public String getParentId() { return parentId; } public void setParentId(String parentId) { this.parentId = parentId; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public String getTenantId() { return tenantId; } public void setTenantId(String tenantId) { this.tenantId = tenantId; } @Override public String toString() { return this.getClass().getSimpleName() + "[id=" + id + ", catalogCode=" + catalogCode + ", catalogName=" + catalogName + ", parentId=" + parentId + ", createTime=" + createTime + ", tenantId=" + tenantId + "]"; } }
3. 创建mybatis mapper文件
mapper文件命名为ProcessCatalog.xml
insert into ${prefix}ACT_RE_PROC_CATALOG(ID_, CATALOG_CODE_, CATALOG_NAME_, PARENT_ID_, CREATE_TIME_, TENANT_ID_) values(#{id, jdbcType=VARCHAR}, #{catalogCode, jdbcType=VARCHAR}, #{catalogName, jdbcType=VARCHAR}, #{parentId, jdbcType=VARCHAR}, #{createTime, jdbcType=TIMESTAMP}, #{tenantId, jdbcType=VARCHAR}) update ${prefix}ACT_RE_PROC_CATALOG PROCDEF_ = #{procdef, jdbcType=VARCHAR}, CATALOG_CODE_ = #{catalogCode, jdbcType=VARCHAR}, CATALOG_NAME_ = #{catalogName, jdbcType=VARCHAR}, PARENT_ID_ = #{parentId, jdbcType=VARCHAR}, CREATE_TIME_ = #{createTime, jdbcType=TIMESTAMP}, TENANT_ID_ = #{tenantId, jdbcType=VARCHAR} where ID_= #{id, jdbcType=VARCHAR} delete from ${prefix}ACT_RE_PROC_CATALOG where ID_ = #{id} select * from ${prefix}ACT_RE_PROC_CATALOG where ID_ = #{id} ${limitBefore} select ${distinct} RES.* ${limitBetween} ${orderBy} ${limitAfter} select count(distinct RES.ID_) from ${prefix}ACT_RE_PROC_CATALOG RES RES.ID_ = #{id} and RES.CATALOG_CODE_ = #{catalogCode} and RES.CATALOG_NAME_ = #{catalogName} and RES.PARENT_ID_ = #{parentId} and RES.CREATE_TIME_ < #{createTimeBefore} and RES.CREATE_TIME_ > #{createTimeAfter} and ( RES.TENANT_ID_ in #{tenantId} or RES.TENANT_ID_ is null ) and RES.TENANT_ID_ is null select * from ${prefix}ACT_RE_PROC_CATALOG where PARENT_ID_ = #{parameter.parentId} and CATALOG_CODE_ = #{parameter.catalogCode} and CATALOG_NAME_ = #{parameter.catalogName} and TENANT_ID_ is null and TENANT_ID_ = #{parameter.tenantId} order by CATALOG_CODE_ asc ${limitBefore} select ${distinct} RES.* ${limitBetween} ${orderBy} ${limitAfter} select count(distinct RES.ID_)
4. 创建数据查询类
按照camunda的规则,创建查询类必须基于接口,所以先创建查询接口,接口命名为ProcessCatalogQuery.java。
import org.camunda.bpm.engine.impl.QueryPropertyImpl; import org.camunda.bpm.engine.query.Query; import org.camunda.bpm.engine.query.QueryProperty; import java.util.Date; /** * 流程分类查询接口 */ public interface ProcessCatalogQuery extends Query<ProcessCatalogQuery, ProcessCatalog>{ public static final QueryProperty CATALOG_CODE = new QueryPropertyImpl("CATALOG_CODE_"); public static final QueryProperty CREATE_TIME = new QueryPropertyImpl("CREATE_TIME_"); public static final QueryProperty TENANT_ID = new QueryPropertyImpl("TENANT_ID_"); ProcessCatalogQuery id(String id); ProcessCatalogQuery catalogCode(String catalogCode) ; ProcessCatalogQuery catalogName(String catalogName); ProcessCatalogQuery parentId(String parentId) ; ProcessCatalogQuery createTimeBefore(Date before); ProcessCatalogQuery createTimeAfter(Date after) ; ProcessCatalogQuery tenantIdIn(String... tenantIds) ; ProcessCatalogQuery withoutTenantId() ; ProcessCatalogQuery orderByCatalogCode(); ProcessCatalogQuery orderByCreateTime(); ProcessCatalogQuery orderByTenantId(); }
然后创建查询实现类,命名为ProcessCatalogQueryImpl.java
import org.camunda.bpm.engine.impl.interceptor.CommandContext; import org.camunda.bpm.engine.impl.interceptor.CommandExecutor; import org.camunda.bpm.engine.impl.util.CompareUtil; import org.camunda.bpm.engine.repository.ProcessCatalog; import org.camunda.bpm.engine.repository.ProcessCatalogQuery; import java.io.Serializable; import java.util.Date; import java.util.List; import static org.camunda.bpm.engine.impl.util.EnsureUtil.ensureNotNull; /** * 流程表单配置查询实现 */ public class ProcessCatalogQueryImpl extends AbstractQuery<ProcessCatalogQuery, ProcessCatalog> implements ProcessCatalogQuery, Serializable { private static final long serialVersionUID = 1L; protected String id; protected String catalogCode; protected String catalogName; protected String parentId; protected Date createTime; protected String tenantId; protected Date createTimeBefore; protected Date createTimeAfter; protected boolean isTenantIdSet = false; protected String[] tenantIds; public ProcessCatalogQueryImpl() { } public ProcessCatalogQueryImpl(CommandExecutor commandExecutor) { super(commandExecutor); } public ProcessCatalogQuery id(String id) { ensureNotNull("Id ", id); this.id = id; return this; } public ProcessCatalogQuery catalogCode(String catalogCode) { ensureNotNull("catalogCode", catalogCode); this.catalogCode = catalogCode; return this; } public ProcessCatalogQuery catalogName(String catalogName) { ensureNotNull("catalogName", catalogName); this.catalogName = catalogName; return this; } public ProcessCatalogQuery parentId(String parentId) { ensureNotNull("parentId", parentId); this.parentId = parentId; return this; } public ProcessCatalogQuery createTimeBefore(Date before) { ensureNotNull("createTimeBefore", before); this.createTimeBefore = before; return this; } public ProcessCatalogQuery createTimeAfter(Date after) { ensureNotNull("createTimeAfter", after); this.createTimeAfter = after; return this; } public ProcessCatalogQuery tenantIdIn(String... tenantIds) { ensureNotNull("tenantIds", (Object[]) tenantIds); this.tenantIds = tenantIds; isTenantIdSet = true; return this; } public ProcessCatalogQuery withoutTenantId() { isTenantIdSet = true; this.tenantIds = null; return this; } protected boolean hasExcludingConditions() { return super.hasExcludingConditions() || CompareUtil.areNotInAscendingOrder(createTimeAfter, createTimeBefore); } public ProcessCatalogQuery orderByCatalogCode() { return orderBy(ProcessCatalogQuery.CATALOG_CODE); } public ProcessCatalogQuery orderByCreateTime() { return orderBy(ProcessCatalogQuery.CREATE_TIME); } public ProcessCatalogQuery orderByTenantId() { return orderBy(ProcessCatalogQuery.TENANT_ID); } @Override public long executeCount(CommandContext commandContext) { checkQueryOk(); return commandContext.getProcessCatalogManager().findProcessCatalogCountByQueryCriteria(this); } @Override public List executeList(CommandContext commandContext, Page page) { checkQueryOk(); return commandContext.getProcessCatalogManager().findProcessCatalogsByQueryCriteria(this, page); } public String getId() { return id; } public String getCatalogCode() { return catalogCode; } public String getCatalogName() { return catalogName; } public String getParentId() { return parentId; } public Date getCreateTimeBefore() { return createTimeBefore; } public Date getCreateTimeAfter() { return createTimeAfter; } }
5. 创建数据库操作类
数据库操作类类似于DAO类,camunda的规则为xxxManager,我们命名该类为ProcessCatalogManager.java
import org.camunda.bpm.engine.impl.Page; import org.camunda.bpm.engine.impl.ProcessCatalogQueryImpl; import org.camunda.bpm.engine.impl.db.ListQueryParameterObject; import org.camunda.bpm.engine.impl.persistence.AbstractManager; import org.camunda.bpm.engine.repository.ProcessCatalog; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 流程分类数据库操作类 */ public class ProcessCatalogManager extends AbstractManager { public void insertProcessCatalog(ProcessCatalogEntity processCatalogEntity) { getDbEntityManager().insert(processCatalogEntity); getDbEntityManager().update(ProcessCatalogEntity.class,"updateProcessCatalog",processCatalogEntity); } public void updateProcessCatalog(ProcessCatalogEntity processCatalogEntity) { getDbEntityManager().update(ProcessCatalogEntity.class,"updateProcessCatalog",processCatalogEntity); } public void deleteProcessCatalog(String id, final boolean cascade) { if (cascade) { } getDbEntityManager().delete(ProcessCatalogEntity.class, "deleteProcessCatalog", id); } public List findProcessCatalogsByParentId(String parentId) { Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put("parentId", parentId); ListQueryParameterObject parameterObject = new ListQueryParameterObject(); parameterObject.setParameter(parameters); List list = getDbEntityManager().selectList("selectProcessCatalogsByProcdef", parameterObject); return list; } public ProcessCatalogEntity findProcessCatalogById(String id) { return getDbEntityManager().selectById(ProcessCatalogEntity.class, id); } public long findProcessCatalogCountByQueryCriteria(ProcessCatalogQueryImpl processCatalogQuery) { configureQuery(processCatalogQuery); return (Long) getDbEntityManager().selectOne("selectProcessCatalogCountByQueryCriteria", processCatalogQuery); } @SuppressWarnings("unchecked") public List findProcessCatalogsByQueryCriteria(ProcessCatalogQueryImpl processCatalogQuery, Page page) { configureQuery(processCatalogQuery); return getDbEntityManager().selectList("selectProcessCatalogsByQueryCriteria", processCatalogQuery, page); } @Override public void close() { } @Override public void flush() { } protected void configureQuery(ProcessCatalogQueryImpl query) { getAuthorizationManager().configureCatalogQuery(query); getTenantManager().configureQuery(query); } }
6. 在mybatis中注册mapping
我们自定义的的mapping文件需要注册到全局的mappings.xml中,其实就是mybatis的机制,找到mappings.xml文件,增加如下一条记录。
<mapper resource="org/camunda/bpm/engine/impl/mapping/entity/ProcessCatalog.xml" />
7. 在上下文中注册数据库操作类
Camunda中大量应用了命令模式,有自己的一套事务管理机制,数据库操作类必须要在CommandContext.java中进行注册。
public ProcessCatalogManager getProcessCatalogManager() { return getSession(ProcessCatalogManager.class); }
8. 在全局配置中注册数据库操作类
在ProcessEngineConfigurationImpl.java类的initSessionFactories方法中注册数据库操作类ProcessCatalogManager。
addSessionFactory(new GenericManagerFactory(ProcessCatalogManager.class));
总结
通过以上的8个步骤,就可以在camunda中任意扩展数据库表了,同时我们也深入了解camunda原生数据操作机制。
这篇关于开源流程引擎Camunda BPM如何扩展数据库表的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享