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

解決環境搭建中的問題(過程記錄)

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進行解決,在解決錯誤的過程中也要靈活機變,畢竟錯誤不一定是相同的,要相互啓發,勇於實踐,敢於實驗,一步一個腳印的解決錯誤。

補充

Q1

1、在進行如上配置以後JPA查詢不到結果或無法插入數據,一個原因是hibernate.hbm2ddl.auto使用了createcreate-drop屬性,這樣會新建一張空表或在代碼執行結束以後刪除數據庫表。
2、當hibernate.hbm2ddl.auto使用了noneupdate屬性後可能會出現,SQLSyntaxErrorException:Unknown column 'xxxxxxx' in 'field list' 的情況。

A1

解決辦法是,JPA查詢不到數據是因爲hibernate.hbm2ddl.auto使用了createcreate-drop屬性,因爲這樣會覆蓋原來的數據表,在實體類的屬性名稱上加@Column註解,就能解決第二個問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章