Create a new SpringBoot project with the following pom.xml file

<? The 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 > < the parent > < groupId > org. Springframework. Boot < / groupId > The < artifactId > spring - the boot - starter - parent < / artifactId > < version > 1.5.9. RELEASE < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <groupId>com.example</groupId> The < artifactId > springboot_tx_chain < / artifactId > < version > 0.0.1 - the SNAPSHOT < / version > < name > springboot_tx_chain < / name > <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId>  </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>2.7.9</version> </dependency> <groupId>mysql</groupId> < artifactId > mysql connector - Java < / artifactId > < version > 5.1.38 < / version > < / dependency > <! -- https://mvnrepository.com/artifact/org.springframework.data/spring-data-commons --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-commons</artifactId> <version>1.13.7.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>Copy the code

The overall structure of the project is as follows

The application.properties file is shown below, where two databases are used to simulate a distributed environment

spring.ds_1.url=jdbc:mysql://localhost:3306/test01
spring.ds_1.username=root
spring.ds_1.password=root
spring.ds_1.driver-class-name=com.mysql.jdbc.Driver

spring.ds_2.url=jdbc:mysql://localhost:3306/test02
spring.ds_2.username=root
spring.ds_2.password=root
spring.ds_2.driver-class-name=com.mysql.jdbc.Driver
Copy the code

The dbConfiguration. class class is as follows:

package com.config;

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.dao.support.ChainedPersistenceExceptionTranslator;
import org.springframework.data.transaction.ChainedTransactionManager;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
public class DBConfiguration {


@Bean
@Primary
@ConfigurationProperties(prefix = "spring.ds_1")
public DataSourceProperties user1DataSourceProperty() {
      return new DataSourceProperties();
}

@Bean
@Primary
public DataSource user1DataSource() {
    return user1DataSourceProperty().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

@Bean
public JdbcTemplate user1JdbcTemplate(@Qualifier("user1DataSource") DataSource dataSource) {
    return new JdbcTemplate(dataSource);
}


@Bean
@ConfigurationProperties(prefix = "spring.ds_2")
public DataSourceProperties user2DataSourceProperty() {
    return new DataSourceProperties();
}

@Bean
public DataSource user2DataSource() {
    return user2DataSourceProperty().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

@Bean
public JdbcTemplate user2JdbcTemplate(@Qualifier("user2DataSource") DataSource dataSource) {
    return new JdbcTemplate(dataSource);
}


@Bean
public PlatformTransactionManager transactionManager() {
    DataSourceTransactionManager user1TR = new DataSourceTransactionManager(user1DataSource());
    DataSourceTransactionManager user2TR = new DataSourceTransactionManager(user2DataSource());
    ChainedTransactionManager chainedTransactionManager = new ChainedTransactionManager(user1TR,user2TR);
    return chainedTransactionManager;
}
Copy the code

}

PeopleService. Class:

package com.service; import com.entity.People; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class PeopleService { @Autowired @Qualifier("user1JdbcTemplate") private JdbcTemplate user1JdbcTemplate;  @Autowired @Qualifier("user2JdbcTemplate") private JdbcTemplate user2JdbcTemplate; @Transactional public void addPeople(People people) { user1JdbcTemplate.update("insert into people (name) values (?) ",people.getName()); user2JdbcTemplate.update("insert into people (name) values (?) ",people.getName()); // Throw an exception to roll back multiError(); } public void multiError() { throw new RuntimeException("Error data"); }Copy the code

}

People.class:

package com.entity;

public class People {

private int id;
private String name;

public People() {
}

public People(int id, String name) {
    this.id = id;
    this.name = name;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
Copy the code

}

PeopleController.class:

import com.entity.People;
import com.service.PeopleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/people")
public class PeopleController {


@Autowired private PeopleService peopleService;

@GetMapping("/savePeople")
public String savePeople() {
    People people = new People();
    people.setName("admin_2");
    peopleService.addPeople(people);
    return "success";
}
Copy the code

}