• Activiti工作流搭建---初始化数据库


    Activiti介绍

    Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理、工作流、服务协作等领域的一个开源的、灵活的、易扩展的可执行流程语言框架。Activiti基于Apache许可的开源BPM平台,创始人Tom Baeyens是JBoss jBPM的项目架构师,它特色是提供了eclipse插件,开发人员可以通过插件直接绘画出业务

    流程图。

    1.工作流引擎

    ProcessEngine对象,这是Activiti工作的核心。负责生成流程运行时的各种实例及数据、监控和管理流程的运行。

    2. BPMN

    业务流程建模与标注(Business Process Model and Notation,BPMN) ,描述流程的基本符号,包括这些图元如何组合成一个业务流程图(Business Process Diagram)

    3. 数据库

    Activiti数据库支持:

    Activiti的后台是有数据库的支持,所有的表都以ACT_开头。 第二部分是表示表的用途的两个字母标识。 用途也和服务的API对应。

    ACT_RE_*: 'RE'表示repository。 这个前缀的表包含了流程定义和流程静态资源 (图片,规则,等等)。

    ACT_RU_*: 'RU'表示runtime。 这些运行时的表,包含流程实例,任务,变量,异步任务,等运行中的数据。 Activiti只在流程实例执行过程中保存这些数据, 在流程结束时就会删除这些记录。 这样运行时表可以一直很小速度很快。

    ACT_ID_*: 'ID'表示identity。 这些表包含身份信息,比如用户,组等等。

    ACT_HI_*: 'HI'表示history。 这些表包含历史数据,比如历史流程实例, 变量,任务等等。

    ACT_GE_*: 通用数据, 用于不同场景下,如存放资源文件。

    4. 下载库activiti

    地址:http://activiti.org/download.html

    5. 解压后的目录

    database文件夹中就是关于数据库的相关文件脚本

    create文件夹中就是Activiti所有支持的数据库脚本文件

    activiti-engine.jar包中自带了创建activiti工作流数据库表的SQL语句和自动初始化数据库的方法。SQL语句在org.activiti.db.create包下,初始化方法在org.activiti.engine.impl.db.DbSchemaCreate的main方法之中。

     源码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class DbSchemaCreate {
     
      public static void main(String[] args) {
        ProcessEngineConfiguration
          .createProcessEngineConfigurationFromResourceDefault()
          .setDatabaseSchemaUpdate(ProcessEngineConfigurationImpl.DB_SCHEMA_UPDATE_CREATE)
          .buildProcessEngine();
      }
     
    }

    以上都是以5.21版本的包为例。由第一张图可以看出两点:(一)目前activiti支持的数据库类型有:db2、h2、hsql、mssql、mysql、oracle和postgres数据库。(二)activiti的数据库表核心在于engine,identity和history是分离了出来。根据官方指导手册的说法,activiti的history功能是可以选择是否开启的,如果不需要自然不用history相关的表,而identity和用户以及用户组相关的表也是不一定需要的,可以使用自己的用户结构表(具体怎么做还没有尝试)。

      初始化数据库的代码很简单,其实际上就是使用配置文件创建了一个工作流引擎,只是将配置项中的databaseSchemaUpdate改成了create,这句就是创建数据库的含义。下面详细说一下具体操作步骤,本次操作是基于maven的,不会的需要自己手动导入包,使用maven也是为了不用下载依赖包。数据库使用的是mysql。开发工具用的eclipse。

      主要步骤有四步:

      1.添加activiti-engine.jar包以及其依赖包到构建路径

      2.添加mysql-connector-java包,mysql数据库的驱动包

      3.编写activiti.cfg.xml配置文件,将其放入classpath下,maven项目就是src/main/resources下就行了。

      4.运行DbSchemaCreate的main方法

      下面是相关操作:

      1.新建一个maven项目,这个就不讲了。在pom.xml中添加activiti-engine依赖:

    1
    2
    3
    4
    5
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-engine</artifactId>
        <version>5.21.0</version>
    </dependency>

      2.添加mysql数据库驱动依赖

    1
    2
    3
    4
    5
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>

      3.在src/main/resources下新建一个文件,命名为activiti.cfg.xml(不能是其它的名字)。在里面配置以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd">
                                
           <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">      
                <property name="databaseType" value="mysql"></property> <!-- 数据库类型,最好配置一下 -->
                <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti"></property>   <!-- 数据库URL,我放在名为activiti数据库中 -->
                <property name="jdbcDriver" value="com.mysql.jdbc.Driver"></property>   <!-- 数据库驱动类 mysql是这个,其它的数据库修改一下即可 -->
                <property name="jdbcUsername" value="root"></property>  <!-- 连接数据库的账号 -->
                <property name="jdbcPassword" value="root"></property>  <!-- 连接数据库的密码 -->
                <!-- <property name="databaseSchema" value="activiti"></property> --> <!-- 这个属性可能会用到,后面会进行说明 -->
           </bean>
            
    </beans>

      里面的相关配置databaseType,jdbcUrl等5个配置项,改成自己的相符合的就行了。

      4.eclipse中选中项目,右击选择Run As->Java Application,在弹出的框Select type中输入DBSchemaCreate,选择Matching items中相应的类,点击OK即可,如图:

      如果没什么问题,用工具查看数据库,应该是能够看到自动创建出来的25张表的。

      但是有的时候会出现一些问题。oracle数据库中,如果存在一个用户建了这些表,而我使用另一个用户建这些表会失败。或者是建好表后,将用户删除,再重新创建这个用户,一样会导致创建表失败,提示:表或视图不存在。这个问题的产生与程序执行和oracle数据库的机制有关。

      首先看程序,启动项目后会验证一次数据库的表结构版本和当前jar包版本是否匹配,这个流程是为了校验而已。而在初始化数据库的时候一般不会执行这个校验,但是当错误的判定数据库的表存在时,会错误的进入校验数据库表结构版本的分支之中,导致原本数据库还没有初始化表,却去查询表act_ge_property(存放了版本信息),自然而然地报了表或视图不存在了。问题在于为什么明明表不存在,却判定表示存在的。

      查看异常链追踪源代码会发现其实际上判断的是表act_ru_execution是否存在。其从DbSqlSession的dbSchemaCreate()方法开始:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public void dbSchemaCreate() {
      if (isEngineTablePresent()) {
        String dbVersion = getDbVersion();
        if (!ProcessEngine.VERSION.equals(dbVersion)) {
          throw new ActivitiWrongDbException(ProcessEngine.VERSION, dbVersion);
        }
      else {
        dbSchemaCreateEngine();
      }
     
      if (dbSqlSessionFactory.isDbHistoryUsed()) {
        dbSchemaCreateHistory();
      }
     
      if (dbSqlSessionFactory.isDbIdentityUsed()) {
        dbSchemaCreateIdentity();
      }
    }

      这段代码很清楚地展示了相关关系,先判断表是否存在,存在就验证版本号,不存在就创建engine,后面判断history和identity是否被使用(默认使用),使用了就创建相关的表。这里很明显就是isEngineTablePresent()返回了true才导致了这个问题,继续追踪到这个类中的isTablePresent()方法,其真正作用的是下面这段:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public static String[] JDBC_METADATA_TABLE_TYPES = {"TABLE"};
     
     
          try {
            tables = databaseMetaData.getTables(catalog, schema, tableName, JDBC_METADATA_TABLE_TYPES);
            return tables.next();
          finally {
            try {
              tables.close();
            catch (Exception e) {
              log.error("Error closing meta data tables", e);
            }
          }

      tables.next()返回了true,那么问题肯定是出在了databaseMetaData.getTables()这条语句上。断点发现前两个参数都是null,tableName就是验证的表act_ru_execution。最后一个上面以给出,就是字符串数组,里面只有一个“TABLE”字符串。这个方法具体出在第二个参数上面。具体的参数含义可以百度,这里提供一个链接(勿删):http://blog.sina.com.cn/s/blog_707a9f0601014y1a.html

      第二个参数对于oracle数据库来说比较重要,就像之前说的造成这个问题的两种可能的场景。如果出现了这个问题,就需要配置,使schema这个参数为大写的登陆用户名(必须大写,与oracle的机制有关)。这个参数的设置,不断向上查找源码,会发现只需要在配置文件中配置databaseSchema属性就可以了(value大写)。mysql数据库应该就没有太大问题了。

      最后简单介绍一下activiti数据库表的组成。之前看创建数据库的sql语句就很清楚,表分为必要的engine和非必要的history以及identity。

          其中act_hi_*这8张表就与history相关。act_id_*这4张与identity有关。剩余的全是engine必备的表,也可以简单的分下类:act_ru_*这6张表是runtime流程运行中相关的表。act_re_*这3张表是repository这个是管理部署和流程定义相关的表,基本不会改变,除非更改部署和流程定义。act_ge_property存放了数据库表版本的相关信息,只有在升级版本的时候会改变。act_ge_bytearray存放了一些字节流数据,一般是各种资源数据如流程定义的xml,流程图等。act_evt_log看名字就知道是事件日志的表,如何使用暂时不知。最后一张act_procdef_info表看名字也就是流程定义详情表。那些归类了得表具体作用看*,其后缀的名字,大概就知道其具体作用,如:task(任务)、variable(变量)等,这里就不一一介绍了。

  • 相关阅读:
    列表组件抽象(5)-简洁易用的表格组件
    列表组件抽象(4)-滚动列表及分页说明
    列表组件抽象(3)-分页和排序管理说明
    列表组件抽象(2)-listViewBase说明
    列表组件抽象(1)-概述
    简单实用的进度条加载组件loader.js
    简单封装分页功能pageView.js
    为什么不能用速度与时间的关系去实现动画
    java开发面试题目及答案(持续更新)
    Java Web目前主流比较成熟的框架以及正在兴起的框架
  • 原文地址:https://www.cnblogs.com/zhaosq/p/10095897.html
Copyright © 2020-2023  润新知