Skip to content

Commit

Permalink
feat(root) 新增 starter-jta-atomikos模块
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhengjiaao committed Nov 28, 2022
1 parent 73ee917 commit 7d68aaa
Show file tree
Hide file tree
Showing 25 changed files with 1,014 additions and 12 deletions.
3 changes: 3 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
<modules>
<module>starter-actuator</module>
<module>starter-aop</module>
<module>starter-batch</module>
<module>starter-cache</module>
<module>starter-data</module>
<module>starter-dubbo</module>
<module>starter-freemarker</module>
<module>starter-jdbc</module>
<module>starter-jta-atomikos</module>
<module>starter-mail</module>
<!-- <module>starter-oauth2</module>-->
<module>starter-quartz</module>
Expand Down
276 changes: 276 additions & 0 deletions starter-jta-atomikos/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
# starter-jta-atomikos

**多数据源+jta分布式事务管理**

## 依赖引入

```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
<!--可选的,jpa+mysql/pg库-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.4</version>
</dependency>
```

## 配置 jta-atomikos

JtaTransactionManagerConfig.java

```java
/**
* 统一事务管理
*/
@Configuration
public class JtaTransactionManagerConfig {
/**
* 配置spring的JtaTransactionManager,底层委派给atomikos进行处理
*/
@Primary
@Bean(name = "jtaTransactionManager")
public JtaTransactionManager jtaTransactionManager() {
UserTransactionManager userTransactionManager = new UserTransactionManager();
UserTransaction userTransaction = new UserTransactionImp();
return new JtaTransactionManager(userTransaction, userTransactionManager);
}
}
```

## 配置jpa多数据源

### jpa数据源一

```java
/**
* 配置JPA的数据持久层,需要配置如下内容:
*
* DataSource
* EntityManager
* EntityManagerFactoryBean
* PlatformTransactionManager
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager",
basePackages = PrimaryDataSourceConfig.REPOSITORY_PACKAGE)
public class PrimaryDataSourceConfig {

static final String REPOSITORY_PACKAGE = "com.zja.jta.primary.repository";
private static final String ENTITY_PACKAGE = "com.zja.jta.primary.entity";

@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}

@Primary
@Bean(name = "primaryJpaProperties")
@ConfigurationProperties(prefix = "spring.jpa.primary")
public JpaProperties jpaProperties() {
return new JpaProperties();
}

/**
* 实体管理工厂对象
*
* 将数据源、连接池、以及其他配置策略进行封装返回给事务管理器
* 自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
*/
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("primaryDataSource") DataSource dataSource,
@Qualifier("primaryJpaProperties") JpaProperties jpaProperties,
EntityManagerFactoryBuilder builder) {
return builder
// 设置数据源
.dataSource(dataSource)
// 设置jpa配置
.properties(jpaProperties.getProperties())
//设置实体类所在位置:类或包 entity
.packages(ENTITY_PACKAGE)
//持久化单元名称 用于@PersistenceContext注解获取EntityManager时指定数据源
.persistenceUnit("primaryPersistenceUnit")
.build();
}

/**
* 实体对象管理器
*/
@Primary
@Bean(name = "primaryEntityManager")
public EntityManager entityManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory factory) {
return factory.createEntityManager();
}

/**
* 数据源的事务管理器
*/
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}

}

```

### jpa数据源二

```java
/**
* 配置JPA的数据持久层,需要配置如下内容:
*
* DataSource
* EntityManager
* EntityManagerFactoryBean
* PlatformTransactionManager
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager",
basePackages = SecondaryDataSourceConfig.REPOSITORY_PACKAGE)
public class SecondaryDataSourceConfig {

static final String REPOSITORY_PACKAGE = "com.zja.jta.secondary.repository";
private static final String ENTITY_PACKAGE = "com.zja.jta.secondary.entity";

@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}

@Bean(name = "secondaryJpaProperties")
@ConfigurationProperties(prefix = "spring.jpa.secondary")
public JpaProperties jpaProperties() {
return new JpaProperties();
}

/**
* 实体管理工厂对象
*
* 将数据源、连接池、以及其他配置策略进行封装返回给事务管理器
* 自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
*/
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("secondaryDataSource") DataSource dataSource,
@Qualifier("secondaryJpaProperties") JpaProperties jpaProperties,
EntityManagerFactoryBuilder builder) {
return builder
// 设置数据源
.dataSource(dataSource)
// 设置jpa配置
.properties(jpaProperties.getProperties())
//设置实体类所在位置:类或包 entity
.packages(ENTITY_PACKAGE)
//持久化单元名称 用于@PersistenceContext注解获取EntityManager时指定数据源
.persistenceUnit("secondaryPersistenceUnit")
.build();
}

/**
* 实体对象管理器
*/
@Bean(name = "secondaryEntityManager")
public EntityManager entityManager(@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory factory) {
return factory.createEntityManager();
}

/**
* 数据源的事务管理器
*/
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}

}
```

## yml 配置参考

```yaml
spring:
main:
allow-bean-definition-overriding: true
datasource:
primary:
jdbc-url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC #&rewriteBatchedStatements=true
username: test
password: pass
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
jdbc-url: jdbc:postgresql://localhost:5433/test
username: test
password: pass
driver-class-name: org.postgresql.Driver
jpa:
primary:
show-sql: true
properties:
hibernate:
hbm2ddl:
auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
secondary:
show-sql: true
properties:
hibernate:
hbm2ddl:
auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

```

## 测试示例

```java
@Service
public class JtaService {

//无注解时 抛异常,全部存储
// @Transactional(rollbackFor = Exception.class) //使用jta-atomikos时,抛异常,全部不会存储;不使用jta-atomikos时,抛异常,user不会存储,goods会存储;
// @Transactional(value = "primaryTransactionManager", rollbackFor = Exception.class) //抛异常,user不会存储,goods会存储
// @Transactional(value = "secondaryTransactionManager", rollbackFor = Exception.class) //抛异常,user会存储,goods不会存储
// @Transactional(value = "jtaTransactionManager", rollbackFor = Exception.class) //抛异常,全部存储
public void add_rollback_example() {

PrimaryEntity primaryEntity = new PrimaryEntity();
primaryEntity.setName("数据源1-实体类");
primaryEntity.setCreateTime(new Date());
primaryRepository.save(primaryEntity);

SecondaryEntity secondaryEntity = new SecondaryEntity();
secondaryEntity.setName("数据源2-实体类");
secondaryEntity.setCreateTime(new Date());
secondaryRepository.save(secondaryEntity);

//故意抛出异常测试
int i = 10 / 0;
}

}
```
72 changes: 72 additions & 0 deletions starter-jta-atomikos/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.zja</groupId>
<artifactId>spring-boot-starter-test-root</artifactId>
<version>2.0-SNAPSHOT</version>
</parent>

<groupId>com.zja</groupId>
<artifactId>starter-jta-atomikos</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.4</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @Company: 上海数慧系统技术有限公司
* @Department: 数据中心
* @Author: 郑家骜[ào]
* @Email: [email protected]
* @Date: 2022-07-27 11:09
* @Since:
*/
package com.zja.jta;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class JtaAtomikosApplication {

public static void main(String[] args) {
SpringApplication.run(JtaAtomikosApplication.class, args);
}

}
Loading

0 comments on commit 7d68aaa

Please sign in to comment.