在日常开发中,我们有时需要向两个不同的 MySQL 数据源中的相同数据库和表结构写入数据。这种情况通常在以下场景中出现:
本文将详细讲解如何通过 Spring Boot 配置多数据源,并实现向两个不同 MySQL 数据源中相同的数据库和表结构写入数据。
在开始之前,我们假设有以下环境:
假设数据库和表结构如下:
数据库名称:my_database
表名称:user
表结构:
CREATE TABLE user (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);我们需要将数据同时写入两个数据源,这两个数据源具有相同的数据库和表结构。
在 Spring Boot 中配置多数据源需要一些步骤,包括定义数据源配置、实体管理器、事务管理器以及在代码中使用这些配置。以下是具体实现步骤:
首先,我们需要在 pom.xml 中添加 MySQL 和 Spring Data JPA 相关依赖:
<dependencies>
<!-- Spring Data JPA 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>接下来,在 application.yml 或 application.properties 中配置两个数据源。我们将它们命名为 datasource1 和 datasource2:
spring:
datasource1:
url: jdbc:mysql://localhost:3306/my_database
username: user1
password: password1
driver-class-name: com.mysql.cj.jdbc.Driver
datasource2:
url: jdbc:mysql://localhost:3307/my_database
username: user2
password: password2
driver-class-name: com.mysql.cj.jdbc.Driver为了使 Spring 管理这两个数据源,我们需要定义两个 DataSource Bean 和对应的实体管理器、事务管理器。以下是一个示例实现:
@Configuration
public class DataSourceConfig {
@Bean(name = "dataSource1")
@Primary
@ConfigurationProperties(prefix = "spring.datasource1")
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dataSource2")
@ConfigurationProperties(prefix = "spring.datasource2")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
@Bean(name = "entityManagerFactory1")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory1(EntityManagerFactoryBuilder builder,
@Qualifier("dataSource1") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("com.example.entity") // 实体类包路径
.persistenceUnit("db1")
.build();
}
@Bean(name = "entityManagerFactory2")
public LocalContainerEntityManagerFactoryBean entityManagerFactory2(EntityManagerFactoryBuilder builder,
@Qualifier("dataSource2") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("com.example.entity") // 实体类包路径
.persistenceUnit("db2")
.build();
}
@Bean(name = "transactionManager1")
@Primary
public PlatformTransactionManager transactionManager1(
@Qualifier("entityManagerFactory1") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
@Bean(name = "transactionManager2")
public PlatformTransactionManager transactionManager2(
@Qualifier("entityManagerFactory2") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}假设我们有一个 User 实体类,这个实体类将映射到两个数据库的 user 表:
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String email;
@Column(name = "created_at")
private Timestamp createdAt;
// Getters and setters
}接下来,为 User 实体类创建 JPA Repository 接口:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}现在我们可以编写一个服务类来实现向两个数据源写入相同的数据。我们需要使用 Spring 的事务管理,确保数据一致性。
@Service
public class UserService {
@Autowired
@Qualifier("transactionManager1")
private PlatformTransactionManager transactionManager1;
@Autowired
@Qualifier("transactionManager2")
private PlatformTransactionManager transactionManager2;
@Autowired
private UserRepository userRepository1;
@Autowired
private UserRepository userRepository2;
public void saveUserToBothDataSources(User user) {
TransactionTemplate transactionTemplate1 = new TransactionTemplate(transactionManager1);
TransactionTemplate transactionTemplate2 = new TransactionTemplate(transactionManager2);
// 保存数据到第一个数据源
transactionTemplate1.execute(status -> {
userRepository1.save(user);
return null;
});
// 保存数据到第二个数据源
transactionTemplate2.execute(status -> {
userRepository2.save(user);
return null;
});
}
}在 saveUserToBothDataSources 方法中,我们创建了两个 TransactionTemplate,每个对应一个数据源。这样可以确保在向两个数据源写入数据时,每个数据源的操作都是独立的事务,互不影响。
我们还可以创建一个简单的控制器来调用该服务,并测试多数据源写入的功能:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<String> createUser(@RequestBody User user) {
userService.saveUserToBothDataSources(user);
return ResponseEntity.ok("User saved to both data sources!");
}
}这样,当我们发送 POST 请求到 /user 接口时,就会将 User 实体同时保存到两个数据源中。
在向两个不同 MySQL 数据源的相同数据库与表写入数据时,我们需要进行多数据源的配置,并确保数据源之间的事务隔离与一致性。本文介绍了如何通过 Spring Boot 配置多数据源,并实现同时向两个数据源写入数据的完整过程。希望大家在实际开发中能够根据项目需求选择合适的方案,实现高效、安全的数据操作。