項目中分為了2個數(shù)據(jù)庫 Activiti 數(shù)據(jù)庫和 業(yè)務數(shù)據(jù)庫 下面直接上代碼
- pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<activiti-dependencies.version>7.1.0.M4</activiti-dependencies.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<skipTests>true</skipTests>
</properties>
<!-- 引入Activiti相關依賴 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.activiti.dependencies</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>${activiti-dependencies.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
- application.yml
spring:
datasource:
druid:
master:
# 業(yè)務數(shù)據(jù)庫
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/manage_test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=CTT&rewriteBatchedStatements=true&autoReconnect=true&failOverReadOnly=false
username: root
password: root@123
activiti:
# Activiti 數(shù)據(jù)庫
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/activiti_test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=CTT&rewriteBatchedStatements=true&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true&nullCatalogMeansCurrent=true
# url換為jdbc-url 解決jdbcUrl is required with driverClassName錯誤
jdbc-url: ${spring.datasource.druid.activiti.url}
username: root
password: root@123
# 連接池配置
# 初始化大小,最小蜂挪,最大
initial-size: 10
min-idle: 10
max-active: 20
# 配置一個連接在池中最小生存的時間制市,單位是毫秒
min-evictable-idle-time-millis: 300000
# max-evictable-idle-time-millis: 600000
max-open-prepared-statements: 60000
# 打開PSCache问麸,并且指定每個連接上PSCache的大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
#最大等待超時時間
max-wait: 60000
test-on-borrow: false
test-on-return: false
test-while-idle: true
# 配置間隔多久才進行一次檢測蒂破,檢測需要關閉的空閑連接恒水,單位是毫秒
time-between-eviction-runs-millis: 60000
validation-query: SELECT 1 FROM DUAL
validation-query-timeout: 60000
query-timeout: 60000
transaction-threshold-millis: 60000
remove-abandoned-timeout-millis: 30000
# 配置監(jiān)控統(tǒng)計攔截的filters,采用log4j2作為日志實現(xiàn)
filters: stat,wall,log4j2
# 通過connectProperties屬性來打開mergeSql功能培愁;慢SQL記錄
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多個DruidDataSource的監(jiān)控數(shù)據(jù)
use-global-data-source-stat: true
# 監(jiān)控配置 WebStatFilter配置
web-stat-filter:
enabled: true
exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
principal-cookie-name: admin
principal-session-name: admin
profile-enable: true
session-stat-enable: false
session-stat-max-count: 1000
url-pattern: '/*'
stat-view-servlet:
# IP 白名單
allow: 127.0.0.1
# IP黑名單(共同存在時监氢,deny優(yōu)先于allow)
deny: 192.168.0.10
enabled: true
# 控制臺用戶名和密碼
login-password: admin
login-username: admin
reset-enable: false
url-pattern: '/druid/*'
# 配置日志輸出
filter:
slf4j:
enabled: true
statement-create-after-log-enabled: false
statement-close-after-log-enabled: false
result-set-open-after-log-enabled: false
stat:
#慢查詢
log-slow-sql: true
#慢查詢時長,默認3秒
slow-sql-millis: 1000
merge-sql: false
wall:
config:
multi-statement-allow: true
# jta atomikos 配置
jta:
atomikos:
datasource:
min-pool-size: 10
max-pool-size: 20
borrow-connection-timeout: 60
connectionfactory:
min-pool-size: 10
max-pool-size: 20
borrow-connection-timeout: 60
jpa:
open-in-view: true
database: MYSQL
generate-ddl: true
show-sql: true
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: update
# update:表示自動根據(jù)model對象來更新表結構衅码,啟動 hibernate 時會自動檢查數(shù)據(jù)庫拯刁,如果缺少表則自動建表;缺少列則自動添加列逝段;
# create: 啟動hibernate時筛璧,自動刪除原來的表,新建所有的表惹恃,所以每次啟動后的以前數(shù)據(jù)都會丟失。
# create-drop:應用停下來的時候棺牧,自動會把表和數(shù)據(jù)刪掉巫糙、
# none: 什么也不做;
# validate:會驗證類里的屬性和表字段是否一致颊乘,不一致参淹,則會報錯醉锄;
naming:
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy # 策略會有大小寫區(qū)別 在進行領域映射時,首字母小寫,大寫字母變?yōu)橄聞澗€加小寫 自動根據(jù)實體類重新生成表時(實體類即使配置了@Table 如果大小寫不匹配也會生成表) 表名和字段都為小寫
properties:
hibernate:
format_sql: true
activiti:
# 數(shù)據(jù)源指定
database-schema: ACTIVITI
# 建表規(guī)則: 服務啟動時檢查數(shù)據(jù)庫表浙值,不存在則創(chuàng)建
database-schema-update: true
# 表示哪種情況下使用歷史表恳不,這里配置為all表示全部記錄歷史,方便繪制流程圖; 記錄歷史等級 可配置的歷史級別有none, acitivity, audit, full
history-level: full
# 表示使用歷史表开呐,如果不配置烟勋,則工程啟動后可以檢查數(shù)據(jù)庫
db-history-used: true
# spring jpa使用
jpa-enabled: true
# 暫時不檢查
check-process-definitions: false
- 業(yè)務數(shù)據(jù)庫 數(shù)據(jù)源配置
/***
* 文件名稱: JpaRepositoriesConfig.java
* 文件描述: 默認數(shù)據(jù)源 主庫持久化配置
* 公 司:
* 內(nèi)容摘要:
* 其他說明: @EnableTransactionManagement 開啟注解事物
* @EnableJpaRepositories 開啟JPA存儲庫掃描
* @EntityScan 配置 實體類所在的路徑 解決: Not a managed type:
* 完成日期:
* 修改記錄:
* @version 1.0
* @author
*/
@Configuration
@DependsOn("transactionManager")
@EntityScan(basePackages = {"test.base.entity"})
@EnableJpaRepositories(basePackages = {"test.base.repository.jpa"},
entityManagerFactoryRef = "masterEntityManager", transactionManagerRef = "transactionManager")
public class JpaRepositoriesConfig {
@Autowired
private JpaVendorAdapter jpaVendorAdapter;
@Autowired
private JpaProperties jpaProperties;
@Autowired
private HibernateProperties hibernateProperties;
@Bean("masterDruidDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.master")
public DruidDataSource masterDruidDataSource() {
return new DruidDataSource();
}
/**
* 默認數(shù)據(jù)庫
* @return
*/
@Primary
@Bean(name = "dataSource", initMethod = "init", destroyMethod = "close")
public DataSource masterDataSource() throws SQLException {
DruidDataSource dataSourceProperties = masterDruidDataSource();
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(dataSourceProperties.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setUser(dataSourceProperties.getUsername());
mysqlXaDataSource.setPassword(dataSourceProperties.getPassword());
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("masterDataSource");
xaDataSource.setBorrowConnectionTimeout(60);
xaDataSource.setMaxIdleTime(60);
xaDataSource.setMaxPoolSize(dataSourceProperties.getMaxActive());
xaDataSource.setMinPoolSize(dataSourceProperties.getMinIdle());
return xaDataSource;
}
/**
* 默認數(shù)據(jù)源事物配置
* @return
* @throws Throwable
*/
@Primary
@Bean(name = "masterEntityManager")
@DependsOn("transactionManager")
public LocalContainerEntityManagerFactoryBean masterEntityManager() throws Throwable {
HashMap<String, Object> properties = new HashMap<String, Object>();
// 標注transaction是JTA和JTA平臺是AtomikosJtaPlatform.class.getName()
properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
properties.put("javax.persistence.transactionType", "JTA");
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setJtaDataSource(masterDataSource());
entityManager.setJpaVendorAdapter(jpaVendorAdapter);
entityManager.setPackagesToScan("pers.liujunyi.cloud.photo.entity", "pers.liujunyi.cloud.security.entity");
entityManager.setPersistenceUnitName("masterPersistenceUnit");
// 設置jpa屬性 使用 hibernateProperties.determineHibernateProperties(properties, new HibernateSettings()) 解決不按照配置的JPA 命令策略生成表的問題
entityManager.setJpaPropertyMap(hibernateProperties.determineHibernateProperties(properties, new
HibernateSettings()));
return entityManager;
}
}
- Activiti 數(shù)據(jù)庫 數(shù)據(jù)源配置
/***
* 文件名稱: ActivitiConfig.java
* 文件描述: Activiti 據(jù)源配置
* 公 司:
* 內(nèi)容摘要:
* 其他說明:
* @EnableTransactionManagement 開啟注解事物
* @EnableJpaRepositories 開啟JPA存儲庫掃描
* 完成日期:
* 修改記錄:
* @version 1.0
* @author
*/
@Configuration
@DependsOn("transactionManager")
@EntityScan(basePackages = {"test.activiti.entity"})
@EnableJpaRepositories(basePackages = {"test..activiti.repository"},
entityManagerFactoryRef = "activitiEntityManager", transactionManagerRef = "transactionManager")
public class ActivitiDataSourceConfig extends AbstractProcessEngineAutoConfiguration {
@Autowired
private JpaVendorAdapter jpaVendorAdapter;
@Bean("activitiDruidDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.activiti")
public DruidDataSource activitiDruidDataSource() {
return new DruidDataSource();
}
/**
* Activiti 數(shù)據(jù)源
* @return
*/
@Bean(name = "activitiDataSource", initMethod = "init", destroyMethod = "close")
public DataSource activitiDataSource() throws SQLException {
DruidDataSource dataSourceProperties = activitiDruidDataSource();
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(dataSourceProperties.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setUser(dataSourceProperties.getUsername());
mysqlXaDataSource.setPassword(dataSourceProperties.getPassword());
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("activitiDataSource");
xaDataSource.setBorrowConnectionTimeout(60);
xaDataSource.setMaxIdleTime(60);
xaDataSource.setMaxPoolSize(dataSourceProperties.getMaxActive());
xaDataSource.setMinPoolSize(dataSourceProperties.getMinIdle());
return xaDataSource;
}
/**
*
* @return
* @throws Throwable
*/
@Bean(name = "activitiEntityManager")
@DependsOn("transactionManager")
public LocalContainerEntityManagerFactoryBean masterEntityManager() throws IOException, SQLException {
HashMap<String, Object> properties = new HashMap<>();
// 標注transaction是JTA和JTA平臺是AtomikosJtaPlatform.class.getName()
properties.put("hibernate.transaction.jta.platform", AtomikosJtaPlatform.class.getName());
properties.put("javax.persistence.transactionType", "JTA");
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setJtaDataSource(activitiDataSource());
entityManager.setJpaVendorAdapter(jpaVendorAdapter);
entityManager.setPackagesToScan("pers.liujunyi.cloud.activiti.entity");
entityManager.setPersistenceUnitName("activitiPersistenceUnit");
entityManager.setJpaPropertyMap(properties);
return entityManager;
}
/**
* 注入數(shù)據(jù)源和事務管理器
* 這段代碼很重要,如果沒有這段代碼無法初始化 activitiDataSource
* @param transactionManager
* @param springAsyncExecutor
* @param activitiProperties
* @param processDefinitionResourceFinder
* @param processEngineConfigurationConfigurer
* @param processEngineConfigurators
* @param userGroupManager
* @return
* @throws IOException
*/
@Bean
public SpringProcessEngineConfiguration springProcessEngineConfiguration(
PlatformTransactionManager transactionManager,
SpringAsyncExecutor springAsyncExecutor,
ActivitiProperties activitiProperties,
ProcessDefinitionResourceFinder processDefinitionResourceFinder,
@Autowired(required = false) DefaultActivityBehaviorFactoryMappingConfigurer processEngineConfigurationConfigurer,
@Autowired(required = false) List<ProcessEngineConfigurator> processEngineConfigurators,
UserGroupManager userGroupManager) throws IOException, SQLException {
SpringProcessEngineConfiguration processEngineConfiguration = new SpringProcessEngineConfiguration();
processEngineConfiguration.setConfigurators(processEngineConfigurators);
configureProcessDefinitionResources(processDefinitionResourceFinder, processEngineConfiguration);
processEngineConfiguration.setDataSource(activitiDataSource());
processEngineConfiguration.setTransactionManager(transactionManager);
if (springAsyncExecutor != null) {
processEngineConfiguration.setAsyncExecutor(springAsyncExecutor);
}
processEngineConfiguration.setDeploymentName(activitiProperties.getDeploymentName());
processEngineConfiguration.setDatabaseSchema(activitiProperties.getDatabaseSchema());
processEngineConfiguration.setDatabaseSchemaUpdate(activitiProperties.getDatabaseSchemaUpdate());
processEngineConfiguration.setDbHistoryUsed(activitiProperties.isDbHistoryUsed());
processEngineConfiguration.setAsyncExecutorActivate(activitiProperties.isAsyncExecutorActivate());
if (!activitiProperties.isAsyncExecutorActivate()) {
ValidatorSet springBootStarterValidatorSet = new ValidatorSet("activiti-spring-boot-starter");
springBootStarterValidatorSet.addValidator(new AsyncPropertyValidator());
if (processEngineConfiguration.getProcessValidator() == null) {
ProcessValidatorImpl processValidator = new ProcessValidatorImpl();
processValidator.addValidatorSet(springBootStarterValidatorSet);
processEngineConfiguration.setProcessValidator(processValidator);
} else {
processEngineConfiguration.getProcessValidator().getValidatorSets().add(springBootStarterValidatorSet);
}
}
processEngineConfiguration.setMailServerHost(activitiProperties.getMailServerHost());
processEngineConfiguration.setMailServerPort(activitiProperties.getMailServerPort());
processEngineConfiguration.setMailServerUsername(activitiProperties.getMailServerUserName());
processEngineConfiguration.setMailServerPassword(activitiProperties.getMailServerPassword());
processEngineConfiguration.setMailServerDefaultFrom(activitiProperties.getMailServerDefaultFrom());
processEngineConfiguration.setMailServerUseSSL(activitiProperties.isMailServerUseSsl());
processEngineConfiguration.setMailServerUseTLS(activitiProperties.isMailServerUseTls());
if (userGroupManager != null) {
processEngineConfiguration.setUserGroupManager(userGroupManager);
}
processEngineConfiguration.setHistoryLevel(activitiProperties.getHistoryLevel());
processEngineConfiguration.setCopyVariablesToLocalForTasks(activitiProperties.isCopyVariablesToLocalForTasks());
processEngineConfiguration.setSerializePOJOsInVariablesToJson(activitiProperties.isSerializePOJOsInVariablesToJson());
processEngineConfiguration.setJavaClassFieldForJackson(activitiProperties.getJavaClassFieldForJackson());
if (activitiProperties.getCustomMybatisMappers() != null) {
processEngineConfiguration.setCustomMybatisMappers(
getCustomMybatisMapperClasses(activitiProperties.getCustomMybatisMappers()));
}
if (activitiProperties.getCustomMybatisXMLMappers() != null) {
processEngineConfiguration.setCustomMybatisXMLMappers(
new HashSet<>(activitiProperties.getCustomMybatisXMLMappers()));
}
if (activitiProperties.getCustomMybatisXMLMappers() != null) {
processEngineConfiguration.setCustomMybatisXMLMappers(
new HashSet<>(activitiProperties.getCustomMybatisXMLMappers()));
}
if (activitiProperties.isUseStrongUuids()) {
processEngineConfiguration.setIdGenerator(new StrongUuidGenerator());
}
if (activitiProperties.getDeploymentMode() != null) {
processEngineConfiguration.setDeploymentMode(activitiProperties.getDeploymentMode());
}
processEngineConfiguration.setActivityBehaviorFactory(new DefaultActivityBehaviorFactory());
if (processEngineConfigurationConfigurer != null) {
processEngineConfigurationConfigurer.configure(processEngineConfiguration);
}
return processEngineConfiguration;
}
private void configureProcessDefinitionResources(
ProcessDefinitionResourceFinder processDefinitionResourceFinder,
SpringProcessEngineConfiguration conf) throws IOException {
List<Resource> procDefResources = processDefinitionResourceFinder
.discoverProcessDefinitionResources();
if (!procDefResources.isEmpty()) {
conf.setDeploymentResources(procDefResources.toArray(new Resource[0]));
}
}
}
- atomikos的jta
public class AtomikosJtaPlatform extends AbstractJtaPlatform {
private static final long serialVersionUID = 8601225157421131143L;
static TransactionManager transactionManager;
static UserTransaction transaction;
@Override
protected TransactionManager locateTransactionManager() {
return transactionManager;
}
@Override
protected UserTransaction locateUserTransaction() {
return transaction;
}
}
- 數(shù)據(jù)源事物管理配置
@Configuration
@ComponentScan
@EnableTransactionManagement(proxyTargetClass = true)
public class DataSourceTransactionManagerConfig {
/**
* 事物超時時間 (秒)
*/
@Value("${spring.datasource.druid.transaction-threshold-millis}")
private Integer transactionTimeOut;
@Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
/**
* 設置JPA特性
* @return
*/
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
//顯示sql
hibernateJpaVendorAdapter.setShowSql(true);
//自動生成/更新表
hibernateJpaVendorAdapter.setGenerateDdl(true);
//設置數(shù)據(jù)庫類型
hibernateJpaVendorAdapter.setDatabase(Database.MYSQL);
return hibernateJpaVendorAdapter;
}
@Bean(name = "userTransaction")
public UserTransaction userTransaction() throws Throwable {
UserTransactionImp userTransactionImp = new UserTransactionImp();
userTransactionImp.setTransactionTimeout(60000);
return userTransactionImp;
}
@Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")
public TransactionManager atomikosTransactionManager() throws Throwable {
UserTransactionManager userTransactionManager = new UserTransactionManager();
userTransactionManager.setForceShutdown(false);
userTransactionManager.setTransactionTimeout(60000);
AtomikosJtaPlatform.transactionManager = userTransactionManager;
return userTransactionManager;
}
@Bean(name = "transactionManager")
@DependsOn({"userTransaction", "atomikosTransactionManager"})
public PlatformTransactionManager transactionManager() throws Throwable {
UserTransaction userTransaction = userTransaction();
AtomikosJtaPlatform.transaction = userTransaction;
TransactionManager atomikosTransactionManager = atomikosTransactionManager();
return new JtaTransactionManager(userTransaction, atomikosTransactionManager);
}
}
-
啟動項目 Activiti 數(shù)據(jù)庫 自動生成 25張表
image.png
如果啟動項目沒有自動生成數(shù)據(jù)庫表 請檢查數(shù)據(jù)庫連接地址配置中是否有nullCatalogMeansCurrent=true 配置