解决环境搭建中的问题(过程记录)
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.auto
和hibernate.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张表,历史表没有建立,则流程图及运行节点无法展示
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进行解决,在解决错误的过程中也要灵活机变,毕竟错误不一定是相同的,要相互启发,勇于实践,敢于实验,一步一个脚印的解决错误。
来源:oschina
链接:https://my.oschina.net/u/4317114/blog/4294341