Activiti7整合SpringBoot2.2.7+JPA(Hibernate)+Mysql8.0多数据源配置

倖福魔咒の 提交于 2020-08-10 06:47:58

解决环境搭建中的问题(过程记录)

1、数据源的创建

@Configuration
public class AuditDatasourceConfig extends AbstractProcessEngineAutoConfiguration {
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.act")
    @Qualifier("activitiDataSource")
    public DataSource activitiDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.ihrm")
    @Qualifier("ihrmDataSource")
    public DataSource ihrmDataSource() {
        return DataSourceBuilder.create().build();
    }
}

2、多数据源的持久化配置

@Configuration
@EnableJpaRepositories(
	basePackages = "com.ihrm.audit.dao",
	entityManagerFactoryRef = "ihrmEntityManager",
	transactionManagerRef = "ihrmTransactionManager"
)
public class JpaRepositoriesConfig {

	@Autowired
	private Environment env;

	@Autowired
	@Qualifier("ihrmDataSource")
	private DataSource ihrmDataSource;

	@Bean
	@Primary
	public LocalContainerEntityManagerFactoryBean ihrmEntityManager() {
		LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
		em.setDataSource(ihrmDataSource);
		em.setPackagesToScan(new String[] { "com.ihrm.audit.entity" });
		HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
		em.setJpaVendorAdapter(vendorAdapter);
		HashMap<String, Object> properties = new HashMap<>();
		/************** 第一个问题的出处*************/
		properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
		properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
		/********************************************/
		em.setJpaPropertyMap(properties);
		return em;
	}

	@Primary
	@Bean
	public PlatformTransactionManager ihrmTransactionManager() {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory( ihrmEntityManager().getObject());
		return transactionManager;
	}
}

Q1

问题大致是这样
在这里插入图片描述仔细一看问题主要如下

org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when ‘hibernate.dialect’ not set

原来是

@Autowired
private Environment env;

properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));

的问题,经过测试输出结果查看,果不其然
在这里插入图片描述
其中以下代码

@Autowired
private Environment env;

env.getProperty("hibernate.hbm2ddl.auto")
env.getProperty("hibernate.dialect")

在环境变量中完全吧获取不到任何属性,于是锁定了错误所在。

A1

@Bean
	@Primary
	public LocalContainerEntityManagerFactoryBean ihrmEntityManager() {
		LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
		em.setDataSource(ihrmDataSource);
		em.setPackagesToScan(new String[] { "com.ihrm.audit.entity" });
		HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
		em.setJpaVendorAdapter(vendorAdapter);
		HashMap<String, Object> properties = new HashMap<>();
		/*********修改后的代码********************/
		properties.put("hibernate.hbm2ddl.auto", "update");
		properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
		em.setJpaPropertyMap(properties);
		/*************************************/
		/*System.out.println("*********************************************************************");
		System.out.println(env.getProperty("hibernate.hbm2ddl.auto"));
		System.out.println(env.getProperty("hibernate.dialect"));
		System.out.println("*********************************************************************");*/
		return em;
	}

其中hibernate.hbm2ddl.autohibernate.dialect需要手动设置属性值。
也可以把属性值都设置在配置文件中,之后再通过env去获取。

注:

hibernate.hbm2ddl.auto属性值说明:
自动创建|更新|验证数据库表结构。如果不是此方面的需求建议填写属性值为"none"
create
每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop
每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update
最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据 model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等 应用第一次运行起来后才会。
validate
每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。








Q2

在搭建过程中还会出现这样的错误

Invalid syntax error “type= MyISAM” in DDL generated by Hibernate

A2

原因是开始的时候hibernate.dialect使用的属性值是org.hibernate.dialect.MySQLDialect,在通过Hiberbate自动创建表的时候SQL语句中会使用TYPE,然而在MySQL5.0以后就废弃了这样的语法,统一使用ENGINE。故而,必须把属性值设置为org.hibernate.dialect.MySQL5Dialect

Q3

Unable to build Hibernate SessionFactory; nested exception is java.lang.IllegalArgumentException: jdbcUrl is required with driverClassName.
一看这个错误有些懵,明明加入了JDBC驱动了为啥还来报错!

A3

原因是这样的,在单数据源的时候,在配置文件中直接使用url是可以的,然而现在是都数据源的情况,那么就必须使用jdbc-url作为属性的key

datasource:
    act:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/act?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
      jdbc-url: jdbc:mysql://localhost:3306/act?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
      username: root
      password: 123456
    ihrm:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ihrm?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
      jdbc-url: jdbc:mysql://localhost:3306/ihrm?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
      username: root
      password: 123456

加上jdbc-url就可以解决这个Bug了!

Q4

多数据源的问题解决了,主要矛盾开始向Activiti7转移

java.sql.SQLSyntaxErrorException: Unknown column ‘VERSION_’ in ‘field list’

A4

原因是这样的,一开始使用的是目前最新的Activiti的插件版本

<dependency>
	<groupId>org.activiti</groupId>
	<artifactId>activiti-spring-boot-starter</artifactId>
	<version>7.1.0.M6</version>
</dependency>

这个版本目前如果要自己创建activiti的数据表的话只支持MySQL5.0的版本,也就是需要给数据库降级,这显然不能满足需求,因此,首先需要版本回退,先不使用这个版本插件,我这里直接使用了<version>7.1.0.M2</version>因为合格版本比较老,似乎没有这个Bug。但是如果要Activiti7自动创建数据库也还是不行的,需要通过查阅资料把Activiti7要用的数据表(附件下载SQL)使用MySQL8.0手动创建好,之后填写好配置文件。

activiti:
    # database-schema-update: true
    history-level: full
    db-history-used: true

其中database-schema-update参数会涉及到表的创建与删除,特别说明一下:
flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。
true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。
create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。
drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)



还有history-level
none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等。
db-history-used: true:表示使用历史表,如果不配置,则工程启动后可以检查数据库,只建立了17张表,历史表没有建立,则流程图及运行节点无法展示




activiti数据表描述

Q5

在整合Activiti7的过程中,还出现了java.lang.NullPointerException的错误

A5

原因是Activiti7所需要使用的数据表
在这里插入图片描述
里面没有数据,一般情况下,Activiti7在自动创建这张表之后会加入一些配置信息,那么可以插入如下数据

INSERT INTO `act_ge_property` VALUES ('cfg.execution-related-entities-count', 'false', 1);
INSERT INTO `act_ge_property` VALUES ('next.dbid', '1', 1);
INSERT INTO `act_ge_property` VALUES ('schema.history', 'create(7.0.0.0)', 1);
INSERT INTO `act_ge_property` VALUES ('schema.version', '7.0.0.0', 1);

Q6

在以上有关数据库问题解决后,还会出现一些细枝末节的问题
比如

org.apache.commons.io.IOUtils.toString(Ljava/io/InputStream;Ljava/nio/charset/Charset;)Ljava/lang/String;

java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal

A6

这些问题都可以同意通过引入相应依赖进行解决

<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.6</version>
</dependency>

<dependency>
	<groupId>xml-apis</groupId>
	<artifactId>xml-apis</artifactId>
	<version>1.4.01</version>
</dependency>

对待这些问题的解决办法就是知道了他们是缺少方法或者类,那就进行引入。

总结

这次花了挺长时间来整合Activiti7与SpringBoot2,其中的坑还是真不少,在面对这种新事物整合的时候,需要不怕困难敢于亮剑的精神,面对IDE报出的成堆错误信息,要学会快速锁定错误的方法,那就是快速找到IDE错误日志的最后,锁定错误原因,之后通过Google进行解决,在解决错误的过程中也要灵活机变,毕竟错误不一定是相同的,要相互启发,勇于实践,敢于实验,一步一个脚印的解决错误。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!