iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么在Activiti中自动生成28张数据表
  • 313
分享到

怎么在Activiti中自动生成28张数据表

2023-06-14 05:06:29 313人浏览 独家记忆
摘要

这期内容当中小编将会给大家带来有关怎么在Activiti中自动生成28张数据表,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。@Configurationpublic class Spr

这期内容当中小编将会给大家带来有关怎么在Activiti中自动生成28张数据表,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

@Configurationpublic class SpringBootActivitiConfig {@Beanpublic ProcessEngine processEngine(){   ProcessEngineConfiguration pro=ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();   pro.setJdbcDriver("com.mysql.jdbc.Driver");   pro.setJdbcUrl("xxxx");   pro.setJdbcUsername("xxxx");   pro.setJdbcPassword("xxx");   //避免发布的图片和xml中文出现乱码   pro.setActivityFontName("宋体");   pro.setLabelFontName("宋体");   pro.setAnnotationFontName("宋体");   //数据库更更新策略   pro.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);   return pro.buildProcessEngine();}   @Bean   public RepositoryService repositoryService(){     return processEngine().getRepositoryService();   }   @Bean   public RuntimeService runtimeService(){     return processEngine().getRuntimeService();   }   @Bean   public TaskService taskService(){     return processEngine().getTaskService();   }   ......}

其中,方法pro.setDatabaseSchemaUpdate()可对工作流引擎自带的28张表进行不同策略的更新。

Activiti6.0版本总共有四种数据库表更新策略。

查看这三种策略的静态常量标识,分别如下:

public abstract class ProcessEngineConfiguration {   public static final String DB_SCHEMA_UPDATE_FALSE = "false";   public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";   public static final String DB_SCHEMA_UPDATE_TRUE = "true";   ......}public abstract class ProcessEngineConfigurationImpl extends ProcessEngineConfiguration {   public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create";   ......}
  • flase:默认值,引擎启动时,自动检查数据库里是否已有表,或者表版本是否匹配,如果无表或者表版本不对,则抛出异常。(常用在生产环境);

  • true:若表不存在,自动更新;若存在,而表有改动,则自动更新表,若表存在以及表无更新,则该策略不会做任何操作。(一般用在开发环境);

  • create_drop:启动时自动建表,关闭时就删除表,有一种临时表的感觉。(需手动关闭,才会起作用);

  • drop-create:启动时删除旧表,再重新建表。(无需手动关闭就能起作用);

整个启动更新数据库的过程都是围绕这四种策略,接下来就以这四种策略为主题,撸一下自动更新据库表的底层原理,这一步骤是在引擎启动时所执行的buildProcessEngine()方法里实现。

从该buildProcessEngine方法名上便可以看出,这是一个初始化工作流引擎框架的方法。

怎么在Activiti中自动生成28张数据表

从这里开始,一步一步debug去分析源码实现。

一.初始化工作流的buildProcessEngine()方法——

processEngineConfiguration.buildProcessEngine()是一个抽象方法,主要功能是初始化引擎,获取到工作流的核心api接口:ProcessEngine。通过该API,可获取到引擎所有的service服务。

进入processEngine接口,可以看到,其涵盖了Activiti的所有服务接口:

public interface ProcessEngine {  public static String VERSION = "6.0.0.4";  String getName(); void close();  //流程运行服务类,用于获取流程执行相关信息  RepositoryService getRepositoryService();  //流程运行服务类,用于获取流程执行相关信息  RuntimeService getRuntimeService();  //内置表单,用于工作流自带内置表单的设置  FORMService getFormService();  //任务服务类,用户获取任务信息  TaskService getTaskService();  //获取正在运行或已经完成的流程实例历史信息  HistoryService getHistoryService();  //创建、更新、删除、查询群组和用户  IdentityService getIdentityService();  //流程引擎的管理与维护  ManagementService getManagementService();  //提供对流程定义和部署存储库的访问的服务。  DynamicBpmnService getDynamicBpmnService();  //获取配置类  ProcessEngineConfiguration getProcessEngineConfiguration();  //提供对内置表单存储库的访问的服务。  FormRepositoryService getFormEngineRepositoryService();  org.activiti.form.api.FormService getFormEngineFormService();}

buildProcessEngine()有三个子类方法的重写,默认是用ProcessEngineConfigurationImpl类继承重写buildProcessEngine初始化方法,如下图所示:

怎么在Activiti中自动生成28张数据表

该buildProcessEngine重写方法如下:

@Overridepublic ProcessEngine buildProcessEngine() {  //初始化的方法  init();  //创建ProcessEngine  ProcessEngineImpl processEngine = new ProcessEngineImpl(this); // Activiti 5引擎的触发装置  if (isActiviti5CompatibilityEnabled && activiti5CompatibilityHandler != null) {   Context.setProcessEngineConfiguration(processEngine.getProcessEngineConfiguration());   activiti5CompatibilityHandler.getRawProcessEngine();  } postProcessEngineInitialisation(); return processEngine;}

init()方法里面包含各类需要初始化的方法,涉及到很多东西,这里先暂不一一展开分析,主要先分析与数据库连接初始化相关的逻辑。Activiti6.0底层是通过mybatis来操作数据库的,下面主要涉及到mybatis的连接池与sqlSessionFactory 的创建。

initDataSource():实现动态配置数据库DataSource源

protected boolean usingRelationalDatabase = true;if (usingRelationalDatabase) {  initDataSource();}

该数据库连接模式初始化的意义如何理解,这就需要回到最初引擎配置分析,其中里面有这样一部分代码:

pro.setJdbcDriver("com.Mysql.jdbc.Driver");  pro.setJdbcUrl("xxxx"); pro.setJdbcUsername("xxxx");  pro.setJdbcPassword("xxx");

这部分设置的东西,都是数据库相关的参数,它将传到initDataSource方法里,通过mybatis默认的连接池PooledDataSource进行设置,可以说,这个方法主要是用来创建mybatis连接数据库的连接池,从而生成数据源连接。

public void initDataSource() {  //判断数据源dataSource是否存在  if (dataSource == null) {    /    //判断是否使用JNDI方式连接数据源   if (dataSourceJndiName != null) {    try {     dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName);    } catch (Exception e) {     ......    }   //使用非JNDI方式且数据库地址不为空,走下面的设置   } else if (jdbcUrl != null) {     //jdbc驱动为空或者jdbc连接账户为空    if ((jdbcDriver == null) || (jdbcUsername == null)) {    ......    }    //创建mybatis默认连接池PooledDataSource对象,这里传进来的,就是上面pro.setJdbcDriver("com.mysql.jdbc.Driver")配置的参数,    //debug到这里,就可以清晰明白,配置类里设置的JdbcDriver、JdbcUrl、JdbcUsername、JdbcPassWord等,就是为了用来创建连接池需要用到的;    PooledDataSource pooledDataSource = new PooledDataSource(ReflectUtil.getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword);    if (jdbcMaxActiveConnections > 0) {     //设置最大活跃连接数     pooledDataSource.setPoolMaximuMactiveConnections(jdbcMaxActiveConnections);    }    if (jdbcMaxIdleConnections > 0) {     // 设置最大空闲连接数     pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections);    }    if (jdbcMaxCheckoutTime > 0) {     // 最大checkout 时长     pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime);    }    if (jdbcMaxWaitTime > 0) {     // 在无法获取连接时,等待的时间     pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime);    }    if (jdbcPingEnabled == true) {     //是否允许发送测试SQL语句     pooledDataSource.setPoolPingEnabled(true);    ......    dataSource = pooledDataSource;   }    ......  }  //设置数据库类型  if (databaseType == null) {   initDatabaseType();  }}

initDatabaseType()作用是设置工作流引擎的数据库类型。在工作流引擎里,自带的28张表,其实有区分不同的数据库,而不同数据库其建表语句存在一定差异。

进入到 initDatabaseType()方法看看其是如何设置数据库类型的——

public void initDatabaseType() {   Connection connection = null;   try {     connection = this.dataSource.getConnection();     DatabaseMetaData databaseMetaData = connection.getMetaData();     String databaseProductName = databaseMetaData.getDatabaseProductName();     this.databaseType = databaseTypeMappings.getProperty(databaseProductName);     ......   } catch (SQLException var12) {   ......   } finally {   ......   }}

进入到databaseMetaData.getDatabaseProductName()方法里,可以看到这是一个接口定义的方法:

String getDatabaseProductName() throws SQLException;

这个方法在java.sql包中的DatabaseMetData接口里被定义,其作用是搜索并获取数据库的名称。这里配置使用的是mysql驱动,那么就会被mysql驱动中的jdbc中的DatabaseMetaData实现,如下代码所示:

package com.mysql.cj.jdbc;public class DatabaseMetaData implements java.sql.DatabaseMetaData

在该实现类里,其重写的方法中,将会返回mysql驱动对应的类型字符串

@Override public String getDatabaseProductName() throws SQLException {   return "MySQL"; }

故而,就会返回“MySql”字符串,并赋值给字符串变量databaseProductName,再将databaseProductName当做参数传给

databaseTypeMappings.getProperty(databaseProductName),最终会得到一个 this.databaseType =“MySQL”,也就是意味着,设置了数据库类型databaseType的值为mysql。注意,这一步很重要,因为将在后面生成表过程中,会判断该databaseType的值究竟是代表什么数据库类型。

 String databaseProductName = databaseMetaData.getDatabaseProductName(); this.databaseType = databaseTypeMappings.getProperty(databaseProductName);

该方法对SqlSessionFactory进行 初始化创建:SqlSessionFactory是mybatis的核心类,简单的讲,创建这个类,接下来就可以进行增删改查与事务操作了。

 protected boolean usingRelationalDatabase = true; if (usingRelationalDatabase) { initSqlSessionFactory();}

init()主要都是初始化引擎环境的相关操作,里面涉及到很多东西,但在本篇文中主要了解到这里面会创建线程池以及mybatis相关的初始创建即可。

二、开始进行processEngine 的创建

ProcessEngineImpl processEngine = new ProcessEngineImpl(this);

这部分代码,就是创建Activiti的各服务类了:

public ProcessEngineImpl(ProcessEngineConfigurationImpl processEngineConfiguration) { this.processEngineConfiguration = processEngineConfiguration; this.name = processEngineConfiguration.getProcessEngineName(); this.repositoryService = processEngineConfiguration.getRepositoryService(); this.runtimeService = processEngineConfiguration.getRuntimeService(); this.historicDataService = processEngineConfiguration.getHistoryService(); this.identityService = processEngineConfiguration.getIdentityService(); this.taskService = processEngineConfiguration.getTaskService(); this.formService = processEngineConfiguration.getFormService(); this.managementService = processEngineConfiguration.getManagementService(); this.dynamicBpmnService = processEngineConfiguration.getDynamicBpmnService(); this.asyncExecutor = processEngineConfiguration.getAsyncExecutor(); this.commandExecutor = processEngineConfiguration.getCommandExecutor(); this.sessionFactories = processEngineConfiguration.getSessionFactories(); this.transactionContextFactory = processEngineConfiguration.getTransactionContextFactory(); this.formEngineRepositoryService = processEngineConfiguration.getFormEngineRepositoryService(); this.formEngineFormService = processEngineConfiguration.getFormEngineFormService(); if (processEngineConfiguration.isUsingRelationalDatabase() && processEngineConfiguration.getDatabaseSchemaUpdate() != null) {  commandExecutor.execute(processEngineConfiguration.getSchemaCommandConfig(), new SchemaoperationsProcessEngineBuild()); } ......}

注意,这里面有一段代码,整个引擎更新数据库的相应策略是具体实现,就在这里面:

if (processEngineConfiguration.isUsingRelationalDatabase() && processEngineConfiguration.getDatabaseSchemaUpdate() != null) {  commandExecutor.execute(processEngineConfiguration.getSchemaCommandConfig(), new SchemaOperationsProcessEngineBuild()); }
  • processEngineConfiguration.isUsingRelationalDatabase()默认是true,即代表需要对数据库模式做设置,例如前面初始化的dataSource数据源,创建SqlSessionFactory等,这些都算是对数据库模式进行设置;若为false,则不会进行模式设置与验证,需要额外手动操作,这就意味着,引擎不能验证模式是否正确。

  • processEngineConfiguration.getDatabaseSchemaUpdate()是用户对数据库更新策略的设置,如,前面配置类里设置了pro.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE),若设置四种模式当中的任何一种,就意味着,需要对引擎的数据库进行相应策略操作。

综上,if()判断为true,就意味着,将执行括号里的代码,这块功能就是根据策略去对数据库进行相应的增删改查操作。

commandExecutor.execute()是一个典型的命令模式,先暂时不深入分析,直接点开new SchemaOperationsProcessEngineBuild()方法。

public final class SchemaOperationsProcessEngineBuild implements Command<Object> { public Object execute(CommandContext commandContext) {  DbSqlSession dbSqlSession = commandContext.getDbSqlSession();  if (dbSqlSession != null) {   dbSqlSession.performSchemaOperationsProcessEngineBuild();  }  return null; }}

进入到dbSqlSession.performSchemaOperationsProcessEngineBuild()方法中,接下来,将会看到,在这个方法当中,将根据不同的if判断,执行不同的方法——而这里的不同判断,正是基于四种数据库更新策略来展开的,换句话说,这个performSchemaOperationsProcessEngineBuild方法,才是真正去判断不同策略,从而根据不同策略来对数据库进行对应操作:

public void performSchemaOperationsProcessEngineBuild() {  String databaseSchemaUpdate = Context.getProcessEngineConfiguration().getDatabaseSchemaUpdate();  log.debug("Executing performSchemaOperationsProcessEngineBuild with setting " + databaseSchemaUpdate);   //drop-create模式  if ("drop-create".equals(databaseSchemaUpdate)) {    try {      this.dbSchemaDrop();    } catch (RuntimeException var3) {    }  }  if (!"create-drop".equals(databaseSchemaUpdate) && !"drop-create".equals(databaseSchemaUpdate) && !"create".equals(databaseSchemaUpdate)) {     //false模式    if ("false".equals(databaseSchemaUpdate)) {      this.dbSchemaCheckVersion();    } else if ("true".equals(databaseSchemaUpdate)) {       //true模式      this.dbSchemaUpdate();    }  } else {    //create_drop模式    this.dbSchemaCreate();  }}

这里主要以true模式来讲解,其他基本都类似的实现。

public String dbSchemaUpdate() { String feedback = null; //判断是否需要更新,默认是false boolean isUpgradeNeeded = false; int matchingVersionIndex = -1; //判断是否需要更新或者创建引擎核心engine表,若isEngineTablePresent()为true,表示需要更新,若为false,则需要新创建 if (isEngineTablePresent()) { ...... } else {   //创建表方法,稍后会详细分析  dbSchemaCreateEngine(); } //判断是否需要创建或更新历史相关表 if (this.isHistoryTablePresent()) {   if (isUpgradeNeeded) {      this.dbSchemaUpgrade("history", matchingVersionIndex);    } } else if (this.dbSqlSessionFactory.isDbHistoryUsed()) {    this.dbSchemaCreateHistory(); } //判断是否需要更新群组和用户 if (this.isIdentityTablePresent()) {    if (isUpgradeNeeded) {     this.dbSchemaUpgrade("identity", matchingVersionIndex);    } } else if (this.dbSqlSessionFactory.isDbIdentityUsed()) {     this.dbSchemaCreateIdentity();    } return feedback;}

这里以判断是否需要创建engine表为例,分析下isEngineTablePresent()里面是如何做判断的。其他如历史表、用户表,其判断是否需要创建的逻辑,是类型的。

点击isEngineTablePresent()进去——

public boolean isEngineTablePresent() {  return isTablePresent("ACT_RU_EXECUTION");}

进入到isTablePresent("ACT_RU_EXECUTION")方法里,其中有一句最主要的代码:

tables = databaseMetaData.getTables(catalog, schema, tableName, JDBC_METADATA_TABLE_TYPES);return tables.next();

这两行代码大概意思是,通过"ACT_RU_EXECUTION"表名去数据库中查询该ACT_RU_EXECUTION表是否存在,若不存在,返回false,说明还没有创建;若存在,返回true。

返回到该方法上层,当isEngineTablePresent()返回值是false时,说明还没有创建Activiti表,故而,将执行 dbSchemaCreateEngine()方法来创建28表张工作流表。

if (isEngineTablePresent()) { ...... } else {   //创建表方法  dbSchemaCreateEngine(); }

进入到dbSchemaCreateEngine()方法——里面调用了executeMandatorySchemaResource方法,传入"create"与 "engine",代表着创建引擎表的意思。

protected void dbSchemaCreateEngine() {  this.executeMandatorySchemaResource("create", "engine");}

继续进入到executeMandatorySchemaResource里面——

public void executeMandatorySchemaResource(String operation, String component) {  this.executeSchemaResource(operation, component, this.getResourceForDbOperation(operation, operation, component), false);}

跳转到这里时,有一个地方需要注意一下,即调用的this.getResourceForDbOperation(operation, operation, component)方法,这方法的作用,是为了获取sql文件所存放的相对路径,而这些sql,就是构建工作流28张表的数据库sql。因此,我们先去executeSchemaResource()方法里看下——

public String getResourceForDbOperation(String directory, String operation, String component) {   String databaseType = this.dbSqlSessionFactory.getDatabaseType();  return "org/activiti/db/" + directory + "/activiti." + databaseType + "." + operation + "." + component + ".sql";}

这里的directory即前边传进来的"create",databaseType的值就是前面获取到的“mysql”,而component则是"engine",因此,这字符串拼接起来,就是:"org/activiti/db/create/activiti.mysql.create.engine.sql"。

根据这个路径,我们去Activiti源码里查看,可以看到在org/activiti/db/路径底下,总共有5个文件目录。根据其名字,可以猜测出,create目录下存放的,是生成表的sql语句;drop目录下,存放的是删除表是sql语句;mapping目录下,是mybatis映射xml文件;properties是各类数据库类型在分页情况下的特殊处理;upgrade目录下,则是更新数据库表的sql语句。

怎么在Activiti中自动生成28张数据表

展开其中的create目录,可以进一步发现,里面根据名字区分了不同数据库类型对应的执行sql文件,其中,有db2、h3、hsql、mssql、mysql、mysql55、oracle、postgres这八种类型,反过来看,同时说明了Activiti工作流引擎支持使用这八种数据库。通常使用比较多的是mysql。根据刚刚的路径org/activiti/db/create/activiti.mysql.create.engine.sql,可以在下面截图中,找到该对应路径下的engine.sql文件——

怎么在Activiti中自动生成28张数据表

点击进去看,会发现,这不就是我们常见的mysql建表语句吗!没错,工作流Activiti就是在源码里内置了一套sql文件,若要创建数据库表,就直接去到对应数据库文件目录下,获取到相应的建表文件,执行sql语句建表。这跟平常用sql语句构建表结构没太大区别,区别只在于执行过程的方式而已,但两者结果都是一样的。

怎么在Activiti中自动生成28张数据表

到这里,我们根据其拼接的sql存放路径,找到了create表结构的sql文件,那么让我们回到原来代码执行的方法里:

public void executeMandatorySchemaResource(String operation, String component) {   this.executeSchemaResource(operation, component, this.getResourceForDbOperation(operation, operation, component), false); }

这里通过this.getResourceForDbOperation(operation, operation, component), false)拿到 了mysql文件路径,接下来,将同其他几个参数,一块传入到this.executeSchemaResource()方法里,具体如下:

public void executeSchemaResource(String operation, String component, String resourceName, boolean isOptional) {   InputStream inputStream = null;   try {     //根据resourceName路径字符串,获取到对应engine.sql文件的输入流inputStream,即读取engine.sql文件     inputStream = ReflectUtil.getResourceAsStream(resourceName);     if (inputStream == null) {     ......     } else {       //将得到的输入流inputStream传入该方法       this.executeSchemaResource(operation, component, resourceName, inputStream);     }   } finally {    ......   }}

这一步主要通过输入流InputStream读取engine.sql文件的字节,然后再传入到 this.executeSchemaResource(operation, component, resourceName, inputStream)方法当中,而这个方法,将是Activiti建表过程中的核心所在。

下面删除多余代码,只留核心代码来分析:

private void executeSchemaResource(String operation, String component, String resourceName, InputStream inputStream) {  //sql语句字符串  String sqlStatement = null;  try { //1、jdbc连接mysql数据库    Connection connection = this.sqlSession.getConnection(); //2、分行读取resourceName="org/activiti/db/create/activiti.mysql.create.engine.sql"目录底下的文件数据    byte[] bytes = IoUtil.readInputStream(inputStream, resourceName); //3.将engine.sql文件里的数据分行转换成字符串,换行的地方,可以看到字符串用转义符“\n”来代替    String ddlStatements = new String(bytes);    try {      if (this.isMysql()) {        DatabaseMetaData databaseMetaData = connection.getMetaData();        int majorVersion = databaseMetaData.getDatabaseMajorVersion();        int minorVersion = databaseMetaData.getDatabaseMinorVersion();        if (majorVersion <= 5 && minorVersion < 6) {          //若数据库类型是在mysql 5.6版本以下,需要做一些替换,因为低于5.6版本的MySQL是不支持变体时间戳或毫秒级的日期,故而需要在这里对sql语句的字符串做替换。(注意,这里的majorVersion代表主版本,minorVersion代表主版本下的小版本)          ddlStatements = this.updateDdlForMySqlVersionLowerThan56(ddlStatements);        }      }    } catch (Exception var26) {      ......    }    //4.以字符流形式读取字符串数据    BufferedReader reader = new BufferedReader(new StringReader(ddlStatements));    //5.根据字符串中的转义符“\n”分行读取    String line = this.readNextTrimmedLine(reader);    //6.循环每一行    for(boolean inOraclePlsqlBlock = false; line != null; line = this.readNextTrimmedLine(reader)) {      if (line.startsWith("# ")) {      ......      }      //7.若下一行line还有数据,证明还没有全部读取,仍可执行读取    else if (line.length() > 0) {          if (this.isOracle() && line.startsWith("begin")) {           .......          }            else if ((!line.endsWith(";") || inOraclePlsqlBlock) && (!line.startsWith("/") || !inOraclePlsqlBlock)) {            sqlStatement = this.addSqlStatementPiece(sqlStatement, line);          } else {                    if (inOraclePlsqlBlock) {              inOraclePlsqlBlock = false;            } else {              sqlStatement = this.addSqlStatementPiece(sqlStatement, line.substring(0, line.length() - 1));            }          //10.将建表语句字符串包装成Statement对象            Statement jdbcStatement = connection.createStatement();            try {          //11.最后,执行建表语句到数据库中              jdbcStatement.execute(sqlStatement);              jdbcStatement.close();            } catch (Exception var27) {            ......            } finally {          //12.到这一步,意味着上一条sql建表语句已经执行结束,若没有出现错误话,这时已经证明第一个数据库表结构已经创建完成,可以开始拼接下一条建表语句,              sqlStatement = null;            }          }        }      }      ......    } catch (Exception var29) {      ......    }  }

以上步骤可以归纳下:

  1. jdbc连接mysql数据库;

  2. 分行读取resourceName="org/activiti/db/create/activiti.mysql.create.engine.sql"目录底下的sql文件数据;

  3. 将整个engine.sql文件数据分行转换成字符串ddlStatements,有换行的地方,用转义符“\n”来代替;

  4. 以BufferedReader字符流形式读取字符串ddlStatements数据;

  5. 循环字符流里的每一行,拼接成sqlStatement字符串,若读取到该行结尾有“;”符号,意味着已经拼接成一个完整的create建表语句,这时,跳出该次拼接,直接包装成成Statement对象;值得注意一点是,Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。Statement对象是用于执行不带参数的简单SQL语句,例如本次的create建表语句。

  6. 最后,执行jdbcStatement.execute(sqlStatement),将create建表语句执行进数据库中;

  7. 生成对应的数据库表;

根据debug过程截图,可以更为直观地看到,这里获取到的ddlStatements字符串,涵盖了sql文件里的所有sql语句,同时,每一个完整的creat建表语句,都是以";"结尾的:

怎么在Activiti中自动生成28张数据表

每次执行到";"时,都会得到一个完整的create建表语句:

怎么在Activiti中自动生成28张数据表

执行完一个建表语句,就会在数据库里同步生成一张数据库表,如上图执行的是ACT_GE_PROPERTY表,数据库里便生成了这张表:

怎么在Activiti中自动生成28张数据表

在执行完之后,看idea控制台打印信息,可以看到,我的数据库是5.7版本,引擎在启动过程中分别执行了engine.sql、history.sql、identity.sql三个sql文件来进行数据库表结构的构建。

怎么在Activiti中自动生成28张数据表

到这一步,引擎整个生成表的过程就结束了,以上主要是基于true策略模式,通过对engine.sql的执行,来说明工作流引擎生成表的底层逻辑,其余模式基本都类似,这里就不一一展开分析了。

最后,进入到数据库,可以看到,已成功生成28张ACT开头的工作流自带表——

怎么在Activiti中自动生成28张数据表

上述就是小编为大家分享的怎么在Activiti中自动生成28张数据表了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注编程网精选频道。

--结束END--

本文标题: 怎么在Activiti中自动生成28张数据表

本文链接: https://www.lsjlt.com/news/268228.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 怎么在Activiti中自动生成28张数据表
    这期内容当中小编将会给大家带来有关怎么在Activiti中自动生成28张数据表,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。@Configurationpublic class Spr...
    99+
    2023-06-14
  • Activiti工作流学习笔记之自动生成28张数据库表的底层原理解析
    网上关于工作流引擎Activiti生成表的机制大多仅限于四种策略模式,但其底层是如何实现的,相关文章还是比较少,因此,觉得撸一撸其生成表机制的底层原理。 我接触工作流引擎Activi...
    99+
    2024-04-02
  • jpa自动生成数据表怎么实现
    JPA(Java Persistence API)是JavaEE的一个规范,用于简化Java应用程序与数据库之间的交互。JPA提供了...
    99+
    2023-10-20
    jpa
  • sql两张表数据怎么合并成一张表
    可以通过使用SQL的JOIN操作来合并两张表的数据。下面是一个简单的例子: 假设有两个表,一个是"table1"...
    99+
    2024-04-09
    sql
  • python自动处理数据生成报表
    使用模块xlsxwriterimport xlsxwriterworkbook = xlsxwriter.Workbook('chart.xlsx')     #创建一个Excel文件worksheet = workbook.add_wor...
    99+
    2023-01-31
    报表 数据 python
  • excel表格中日期怎么自动生成
    这篇文章给大家分享的是有关excel表格中日期怎么自动生成的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。表格中日期自动生成的方法:首先打开需要自动生成日期的excel表格,选中一个单元格;然后按键盘上的“ctrl...
    99+
    2023-06-14
  • mybatis自动生成表怎么设置
    MyBatis并不是一个表生成工具,它是一个持久层框架,用于将Java对象映射到数据库表。因此,MyBatis不会自动生成表。如果你...
    99+
    2024-04-02
  • excel怎么自动生成工作表
    Excel可以通过以下步骤来自动生成工作表:1. 打开Excel并创建一个新的工作簿。2. 在工作簿中选择要生成工作表的位置。3. ...
    99+
    2023-10-07
    excel
  • 数据库怎么自动生成实体类
    有多种方法可以自动生成数据库实体类,以下是常见的几种方法:1. 使用ORM框架:许多ORM框架都有自动生成实体类的功能,例如Hibe...
    99+
    2023-08-15
    数据库
  • SQL中怎么生成一张日期维度表
    今天就跟大家聊聊有关SQL中怎么生成一张日期维度表,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。创建表结构我们根据常见的日历表来创建一个含有年,月,...
    99+
    2024-04-02
  • 怎么让java只根据数据库表名自动生成实体类
    这篇文章将为大家详细讲解有关怎么让java只根据数据库表名自动生成实体类,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。根据数据库表名生成实体类公司用的jpa,没有用mybatis。所以也没有用mybati...
    99+
    2023-06-15
  • 怎么在eclipse中实现自动生成构造函数
    本篇文章为大家展示了怎么在eclipse中实现自动生成构造函数,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。方法一:我创建了一个类,里面有两个私有属性age和name。现在构造两个构造函数,一个不带...
    99+
    2023-05-31
    eclipse 构造函数
  • 基于Python实现自动化生成数据报表
    目录前言开发工具环境搭建主要代码前言 不要在用手敲生成Excel数据报表了,用Python自动生成Excel数据报表!废话不多说 让我们愉快地开始吧~ 开发工具 Python版本: ...
    99+
    2024-04-02
  • Python自动生成列表怎么实现
    Python可以使用for循环和列表推导式来自动生成列表。以下是两种常见的方法:1. 使用for循环生成列表:```pythonmy...
    99+
    2023-10-11
    Python
  • 怎么在mysql数据库中创建一张表
    这篇文章主要介绍怎么在mysql数据库中创建一张表,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!具体方法:首先打开MYSQL,创建一个数据库。利用create database +(数据库名称)语句,来出创建数据库。...
    99+
    2023-06-14
  • MySQL中如何自动生成测试数据
    MySQL中可以通过以下几种方法来自动生成测试数据: 使用INSERT INTO语句插入数据:可以编写INSERT INTO语句来...
    99+
    2024-04-30
    MySQL
  • 怎么在Shell中动态生成数组
    本篇文章给大家分享的是有关怎么在Shell中动态生成数组,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。方法一:通过while 循环得到需要的结果:start=1;total=0...
    99+
    2023-06-09
  • Mybatis如何自动生成数据库表的实体类
    第一步引入jar 第二步,配置文本文件 # 数据库驱动jar 路径 本地创库的包 drive.class.path=C:/Users/Administrator/.m2/re...
    99+
    2024-04-02
  • 使用java怎么自动生成数据库文档
    今天就跟大家聊聊有关使用java怎么自动生成数据库文档,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。一、引入pom.xml依赖<dependencies> &n...
    99+
    2023-06-15
  • C++中怎么利用Test自动生成函数
    C++中怎么利用Test自动生成函数,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。静态测试 C++Test内嵌了业界最出名的Effective C++(epcc)...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作