Flowable深入浅出-6 Flowable-Modeler详述之常见问题Table act_ge_property doesn't exist

版权声明:本文为博主原创文章,未经博主允许不得转载。不经过允许copy,讲追究法律责任,欢迎加入我们的学习QQ群967254284,可以相互交流 https://blog.csdn.net/houyj1986/article/details/85546680

6 Flowable-Modeler详述之常见问题Table act_ge_property doesn't exist

问题描述

在配置完Springboot的开发环境以后,启动的时候遇到了这个问题,数据库版本为mysql 5.7,Flowable版本为6.4.0,详细报错如下:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'flowController': Unsatisfied dependency expressed through field 'flowService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'flowServiceImpl': Unsatisfied dependency expressed through field 'repositoryService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'repositoryServiceBean' defined in class path resource [org/flowable/spring/boot/ProcessEngineServicesAutoConfiguration.class]: Unsatisfied dependency expressed through method 'repositoryServiceBean' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'processEngine' defined in class path resource [org/flowable/spring/boot/ProcessEngineServicesAutoConfiguration$AlreadyInitializedAppEngineConfiguration.class]: Unsatisfied dependency expressed through method 'processEngine' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flowableAppEngine': FactoryBean threw exception on object creation; nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: Table 'flowstudy.act_ge_property' doesn't exist
### The error may exist in org/flowable/db/mapping/entity/Property.xml
### The error may involve org.flowable.engine.impl.persistence.entity.PropertyEntityImpl.selectProperty-Inline
### The error occurred while setting parameters
### SQL: select * from ACT_GE_PROPERTY where NAME_ = ?
### Cause: java.sql.SQLSyntaxErrorException: Table 'flowstudy.act_ge_property' doesn't exist
   at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1341) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759) ~[spring-beans-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.9.RELEASE.jar:5.0.9.RELEASE]
   at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
   at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
   at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:1277) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
   at org.springframework.boot.SpringApplication.run(SpringApplication.java:1265) [spring-boot-2.0.5.RELEASE.jar:2.0.5.RELEASE]
   at com.hyj.main.App.main(App.java:22) [classes/:na]
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_191]
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_191]
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_191]
   at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_191]
   at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.0.5.RELEASE.jar:2.0.5.RELEASE]

问题定位

  • 看提示显示表不存在说明数据库中没有该表,此时查看的确没有,但是Flowable启动的时候应该会自动创建表的,说明表创建的逻辑判断发生问题
  • 查看代码发现判断主要函数为:
isEngineTablePresent

代码位于类 ProcessDbSchemaManager中,核心判断存在如下:

 public void schemaCreate() {
        this.getCommonSchemaManager().schemaCreate();
        this.getIdentityLinkSchemaManager().schemaCreate();
        this.getTaskSchemaManager().schemaCreate();
        this.getVariableSchemaManager().schemaCreate();
        this.getJobSchemaManager().schemaCreate();
        //使用这个函数判断是否要创建引擎
        if (this.isEngineTablePresent()) {
            String dbVersion = this.getDbVersion();
            if (!"6.4.0.0".equals(dbVersion)) {
                throw new FlowableWrongDbException("6.4.0.0", dbVersion);
            }
        } else {
            this.dbSchemaCreateEngine();
        }

        if (CommandContextUtil.getDbSqlSession().getDbSqlSessionFactory().isDbHistoryUsed()) {
            this.dbSchemaCreateHistory();
        }

    }

更新的时候,设置databaseSchemaUpdate=true的时候,走update,可以看到如下代码也是使用isEngineTablePresent来判断是否存在

public String schemaUpdate() {
        PropertyEntity dbVersionProperty = null;
        String dbVersion = null;
        String feedback = null;
        boolean isUpgradeNeeded = false;
        int matchingVersionIndex = -1;
        int version6120Index = FlowableVersions.getFlowableVersionIndexForDbVersion("6.1.2.0");
        DbSqlSession dbSqlSession = CommandContextUtil.getDbSqlSession();
        boolean isEngineTablePresent = this.isEngineTablePresent();
        if (isEngineTablePresent) {
            dbVersionProperty = (PropertyEntity)dbSqlSession.selectById(PropertyEntityImpl.class, "schema.version");
            dbVersion = dbVersionProperty.getValue();
            matchingVersionIndex = FlowableVersions.getFlowableVersionIndexForDbVersion(dbVersion);
            isUpgradeNeeded = matchingVersionIndex != FlowableVersions.FLOWABLE_VERSIONS.size() - 1;
        }

        boolean isHistoryTablePresent = this.isHistoryTablePresent();
        if (isUpgradeNeeded && matchingVersionIndex < version6120Index) {
            this.dbSchemaUpgradeUntil6120("engine", matchingVersionIndex);
            if (isHistoryTablePresent) {
                this.dbSchemaUpgradeUntil6120("history", matchingVersionIndex);
            }
        }

        this.getCommonSchemaManager().schemaUpdate();
        this.getIdentityLinkSchemaManager().schemaUpdate();
        this.getTaskSchemaManager().schemaUpdate();
        this.getVariableSchemaManager().schemaUpdate();
        this.getJobSchemaManager().schemaUpdate();
        if (isUpgradeNeeded) {
            dbVersionProperty.setValue("6.4.0.0");
            PropertyEntity dbHistoryProperty;
            if ("5.0".equals(dbVersion)) {
                dbHistoryProperty = (PropertyEntity)CommandContextUtil.getPropertyEntityManager().create();
                dbHistoryProperty.setName("schema.history");
                dbHistoryProperty.setValue("create(5.0)");
                dbSqlSession.insert(dbHistoryProperty);
            } else {
                dbHistoryProperty = (PropertyEntity)dbSqlSession.selectById(PropertyEntity.class, "schema.history");
            }

            String dbHistoryValue = "upgrade(" + dbVersion + "->" + "6.4.0.0" + ")";
            dbHistoryProperty.setValue(dbHistoryValue);
            if (version6120Index > matchingVersionIndex) {
                this.dbSchemaUpgrade("engine", version6120Index);
            } else {
                this.dbSchemaUpgrade("engine", matchingVersionIndex);
            }

            feedback = "upgraded Flowable from " + dbVersion + " to " + "6.4.0.0";
        } else if (!isEngineTablePresent) {
            this.dbSchemaCreateEngine();
        }

        if (isHistoryTablePresent) {
            if (isUpgradeNeeded) {
                if (version6120Index > matchingVersionIndex) {
                    this.dbSchemaUpgrade("history", version6120Index);
                } else {
                    this.dbSchemaUpgrade("history", matchingVersionIndex);
                }
            }
        } else if (dbSqlSession.getDbSqlSessionFactory().isDbHistoryUsed()) {
            this.dbSchemaCreateHistory();
        }

        return feedback;
    }

  • isEngineTablePresent代码实现如下:

可以看到使用的是表ACT_RU_EXECUTION是否存在来判断的

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

  • 进一步跟踪看到isTablePresent的实现如下:
 public boolean isTablePresent(String tableName) {
        DbSqlSession dbSqlSession = this.getDbSqlSession();
        DbSqlSessionFactory dbSqlSessionFactory = dbSqlSession.getDbSqlSessionFactory();
        if (!dbSqlSession.getDbSqlSessionFactory().isTablePrefixIsSchema()) {
            tableName = this.prependDatabaseTablePrefix(tableName);
        }

        Connection connection = null;

        try {
            connection = dbSqlSession.getSqlSession().getConnection();
            DatabaseMetaData databaseMetaData = connection.getMetaData();
            ResultSet tables = null;
            String catalog = dbSqlSession.getConnectionMetadataDefaultCatalog();
            if (dbSqlSessionFactory.getDatabaseCatalog() != null && dbSqlSessionFactory.getDatabaseCatalog().length() > 0) {
                catalog = dbSqlSessionFactory.getDatabaseCatalog();
            }

            String schema = dbSqlSession.getConnectionMetadataDefaultSchema();
            if (dbSqlSessionFactory.getDatabaseSchema() != null && dbSqlSessionFactory.getDatabaseSchema().length() > 0) {
                schema = dbSqlSessionFactory.getDatabaseSchema();
            } else if (dbSqlSessionFactory.isTablePrefixIsSchema() && StringUtils.isNotEmpty(dbSqlSessionFactory.getDatabaseTablePrefix())) {
                schema = dbSqlSessionFactory.getDatabaseTablePrefix();
                if (StringUtils.isNotEmpty(schema) && schema.endsWith(".")) {
                    schema = schema.substring(0, schema.length() - 1);
                }
            }

            String databaseType = dbSqlSessionFactory.getDatabaseType();
            if ("postgres".equals(databaseType)) {
                tableName = tableName.toLowerCase();
            }

            if (schema != null && "oracle".equals(databaseType)) {
                schema = schema.toUpperCase();
            }

            if (catalog != null && catalog.length() == 0) {
                catalog = null;
            }

            boolean var10;
            try {
            //查询元数据中的表,根据schema和tablename查看
                tables = databaseMetaData.getTables(catalog, schema, tableName, JDBC_METADATA_TABLE_TYPES);
                var10 = tables.next();
            } finally {
                try {
                    if (tables != null) {
                        tables.close();
                    }
                } catch (Exception var18) {
                    LOGGER.error("Error closing meta data tables", var18);
                }

            }

            return var10;
        } catch (Exception var20) {
            throw new FlowableException("couldn't check if tables are already present using metadata: " + var20.getMessage(), var20);
        }
    }
  • 我们启动程序跟踪进入,查看使用getTables读取表,如下图所示:
    在这里插入图片描述
    -因为机器上以前其他的mysql数据库中部署过Flowable的表,所以当schema为空的时候搜索mysql的元数据的时候搜索到了历史用的表,但是不在该数据库中,所以程序以为表已经有了,但是其实还是历史的表,到此我们基本上找到原因了。
  • 我们使用的驱动为8.0的驱动,8.0版本驱动将参数 nullCatalogMeansCurrent 的默认值由true改为了false,如果你使用DatabaseMetaData.getTables获取所有的表信息。

解决方案一

把正常的数据库的表导出为sql,手动创建表。

解决方案二(推荐)

mysql的连接字符串中添加上nullCatalogMeansCurrent=true,将schema默认设置为当前连接的schema。

验证结果

在这里插入图片描述

打赏

如果您觉得该文章对您有帮助,欢迎打赏作者,谢谢。
在这里插入图片描述
在这里插入图片描述

版权

版权所有,侵权必究,代码与文章,使用、copy、转载请联系作者。由书山登峰人创作。

猜你喜欢

转载自blog.csdn.net/houyj1986/article/details/85546680