Activiti用Api创建数据库表

使用Activiti API动态创建数据库表
这篇博客讲述了如何通过Activiti的工作流引擎API来创建数据库表,而非使用配置文件。在API创建过程中,需要设置引擎配置对象的属性以确保在启动时创建表。然而,由于引擎仅检查ACT_RU_EXECUTION表,导致历史表和身份识别表的创建可能会引发"表或视图名已存在"的错误。此外,文章还提到了在查询schema.version时可能出现的ACT_GE_PROPERTY表不存在的问题,这可能由于引擎在检查表存在性时的bug,需要通过修改DbSqlSession类中的isTablePresent方法来解决。

先上代码:

public void init() throws Exception{
		DataSource ds = EsenServer.getConnFactoryManager().getDataSource(null, true).getDataSource();
		ConnectionFactory fct = EsenServer.getConnFactoryManager().getDefaultConnectionFactory();
	    	DbDefiner dbf = fct.getDbDefiner();
	  
		ProcessEngineConfiguration pec = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration()
				.setDataSource(ds).setDatabaseType("oracle");
		
		boolean historyTablesNullExist = false;
		boolean historyTablesAllExist = false;
		boolean idTablesAllExist = false;
		boolean idTablesNullExist = false;
		boolean engineTablesNullExist = false;
		boolean engineTablesAllExist = false;
		List<String> missingTableNames = null;
		Connection conn = ds.getConnection();
		try{
			 historyTablesNullExist = tablesNullExist(dbf, conn, historyTables);
			 historyTablesAllExist = tablesAllExist(dbf, conn, historyTables);
			 idTablesNullExist = tablesNullExist(dbf, conn, identityTables);
			 idTablesAllExist = tablesAllExist(dbf, conn, identityTables);
			 engineTablesNullExist = tablesNullExist(dbf, conn, engineTables);
			 engineTablesAllExist = tablesAllExist(dbf, conn, engineTables);
			 missingTableNames = getAllMissingTableNames(dbf, conn);
		}finally{
			if(conn!=null){
				conn.close();
			}
		}	
		/**
		 * 判断数据库中是否有引擎核心表或视图、历史表或视图和身份识别表或视图,
		 * 若都不存在,则给当前ProcessEngineConfiguration添加创建数据库表的属性DatabaseSchemaUpdate;
		 * 若都存在,则不设置创建表的属性DatabaseSchemaUpdate;
		 * 其他情况下,则抛出异常:数据库表[...]缺失
		 */
		if(historyTablesNullExist && idTablesNullExist && engineTablesNullExist){	
			pec.setDatabaseSchemaUpdate(ProcessEngineConfigurationImpl.DB_SCHEMA_UPDATE_CREATE);
		}else if(historyTablesAllExist && idTablesAllExist && engineTablesAllExist){
			//do nothing
		}else{
			throw new Exception("数据库表" + missingTableNames.toString() + "缺失");
		}

		processEngine = pec.buildProcessEngine();
		ProcessEngines.registerProcessEngine(processEngine);
		
		workflow = this;
	}

在这里,不是以配置文件的形式创建引擎的,而是直接以Api编码的形式创建工作流引擎,为了让引擎在构建过程中,创建数据库表,需要给引擎配置对象pec设置属性:

pec.setDatabaseSchemaUpdate(ProcessEngineConfigurationImpl.DB_SCHEMA_UPDATE_CREATE);
这样设置好了后,如果是第一次启动运行是没有问题的,因为最开始我们的数据库里面是没有工作流引擎的数据库表的。但是,在重复运行时,就会报错:表或视图已经存在!

原因是:当我们给工作流引擎的配置对象设置了创建数据库表的属性后,工作流引擎每次启动时都会去执行创建表的动作,而引擎本身只是简单的检查一下当前数据库用户有权限查看的所有数据库表中是否有ACT_RU_EXECUTION这张表,而没有对历史表和身份识别表做检查。所以仍然会再次执行创建历史表和身份识别表的ddl语句,进而引起SQLException:表或视图名已存在!因此,可以看到上面的代码中,有很大一部分是在做数据库表是否存在的检查。

另外还需要注意一点的是:在服务器启动时可能还会报错:当查询schema.version时,ACT_GE_PROPERTY表或视图不存在。而这时当你去查看自己的数据库表时,确实数据库中是没有ACT_GE_PROPERTY这张表的。这就奇怪了,既然没有,为什么引擎在创建数据库表时没有创建这张表呢?这是因为引擎在创建表前做的检查存在bug,引擎在检查数据库表中是否存在表ACT_RU_EXECUTION时,检查的不仅是当前用户的表空间,而且还检查了当前用户有权限查看的所有其他数据库表空间,也就是说如果当前用户具有系统管理员权限,那么只要整个数据库系统中,某个用户的表空间中存在这张名为ACT_RU_EXECUTION的表或视图时,我们的引擎在创建表时就认为该表已经存在,进而不会在我们自己的表空间创建该表。而在查询时,引擎只是在我们的表空间中查找,当然找不到了。因为那张被认为存在的表在某个用户的表空间而不在我们自己的表空间。为了彻底解决这个问题,我们只能修改引擎源代码了,更改引擎检查数据库表是否存在的方法:DbSqlSession类中的isTablePresent方法。至于怎样改,大家看看源代码就应该清楚了,方法会有很多,相信大家各有各的选择,这里就不做讨论了。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值