如何向两个不同 MySQL 数据源的相同数据库与表写入数据

news2024/11/29 18:48:04

个人名片
在这里插入图片描述
🎓作者简介:java领域优质创作者
🌐个人主页:码农阿豪
📞工作室:新空间代码工作室(提供各种软件服务)
💌个人邮箱:[2435024119@qq.com]
📱个人微信:15279484656
🌐个人导航网站:www.forff.top
💡座右铭:总有人要赢。为什么不能是我呢?

  • 专栏导航:

码农阿豪系列专栏导航
面试专栏:收集了java相关高频面试题,面试实战总结🍻🎉🖥️
Spring5系列专栏:整理了Spring5重要知识点与实战演练,有案例可直接使用🚀🔧💻
Redis专栏:Redis从零到一学习分享,经验总结,案例实战💐📝💡
全栈系列专栏:海纳百川有容乃大,可能你想要的东西里面都有🤸🌱🚀

目录

  • 如何向两个不同 MySQL 数据源的相同数据库与表写入数据
    • 一、环境准备
    • 二、配置多数据源
      • 1. 添加依赖
      • 2. 配置数据源属性
      • 3. 定义数据源配置类
      • 4. 定义实体类
      • 5. 定义 Repository 接口
      • 6. 编写服务类实现数据写入
      • 7. 控制器示例
    • 三、注意事项
    • 四、总结

如何向两个不同 MySQL 数据源的相同数据库与表写入数据

在日常开发中,我们有时需要向两个不同的 MySQL 数据源中的相同数据库和表结构写入数据。这种情况通常在以下场景中出现:

  1. 数据库迁移:当我们需要将一个数据库的数据迁移到另一个环境时,可能需要同时写入两个数据源。
  2. 主从数据库:在某些场景下,我们可能需要同时更新主数据库和备份数据库,以确保数据的一致性。
  3. 多数据中心部署:在多数据中心架构中,不同的数据源可能位于不同的数据中心,为了确保数据一致性,需要同时写入多个数据源。

本文将详细讲解如何通过 Spring Boot 配置多数据源,并实现向两个不同 MySQL 数据源中相同的数据库和表结构写入数据。

一、环境准备

在开始之前,我们假设有以下环境:

  1. Spring Boot:我们将使用 Spring Boot 作为项目框架。
  2. MySQL 数据库:我们有两个 MySQL 数据源,分别代表不同的数据库环境。
  3. JPA 或 MyBatis:可以选择使用 JPA 或 MyBatis 作为 ORM 框架,本文将以 JPA 为例进行讲解。

假设数据库和表结构如下:

  • 数据库名称: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 中配置多数据源需要一些步骤,包括定义数据源配置、实体管理器、事务管理器以及在代码中使用这些配置。以下是具体实现步骤:

1. 添加依赖

首先,我们需要在 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>

2. 配置数据源属性

接下来,在 application.ymlapplication.properties 中配置两个数据源。我们将它们命名为 datasource1datasource2

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

3. 定义数据源配置类

为了使 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);
    }
}

4. 定义实体类

假设我们有一个 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
}

5. 定义 Repository 接口

接下来,为 User 实体类创建 JPA Repository 接口:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

6. 编写服务类实现数据写入

现在我们可以编写一个服务类来实现向两个数据源写入相同的数据。我们需要使用 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,每个对应一个数据源。这样可以确保在向两个数据源写入数据时,每个数据源的操作都是独立的事务,互不影响。

7. 控制器示例

我们还可以创建一个简单的控制器来调用该服务,并测试多数据源写入的功能:

@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 实体同时保存到两个数据源中。

三、注意事项

  1. 事务管理:确保每个数据源都有独立的事务管理器,并在操作时使用相应的事务管理器。
  2. 数据一致性:在进行数据写入时,要确保在一个数据源写入成功后,另一个数据源也成功,否则可以通过捕获异常并进行回滚操作来确保一致性。
  3. 性能优化:同时写入两个数据源可能会增加响应时间,特别是在高并发场景下,需要做好性能调优。
  4. 读写分离:如果只是同步写入两个数据源,可能会造成性能瓶颈,可以考虑将读操作和写操作分开,以提高效率。

四、总结

在向两个不同 MySQL 数据源的相同数据库与表写入数据时,我们需要进行多数据源的配置,并确保数据源之间的事务隔离与一致性。本文介绍了如何通过 Spring Boot 配置多数据源,并实现同时向两个数据源写入数据的完整过程。希望大家在实际开发中能够根据项目需求选择合适的方案,实现高效、安全的数据操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2215722.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AcWing 3188:Manacher 算法 → 最长回文子串

【题目来源】https://www.acwing.com/problem/content/3190/【题目描述】 给定一个长度为 n 的由小写字母构成的字符串&#xff0c;求它的最长回文子串的长度是多少。【输入格式】 一个由小写字母构成的字符串。【输出格式】 输出一个整数&#xff0c;表示最长回文子串的长度。…

VSCode创建插件HelloWorld找不到指令解决办法

按照网上的教程执行yo code并且生成成功 但是F5打开调试新窗口后&#xff0c;ctrl shift P&#xff0c;输入helloworld并没有指令提示 原因&#xff1a;当前电脑安装的VSCode版本过低&#xff0c;不支持当前插件的使用&#xff08;因为自动生成的插件总是默认使用最新版VSC…

00 springboot项目创建

我们创建SpringBoot项目有两种方式: Spring Initializr spring initerzie 方式创建: 启动类, 依赖 生成,但是需要网络maven的方式 maven方式创建: 启动类, 依赖, 这些都需要手动编写,但是不需要网络 如果你觉得我分享的内容或者我的努力对你有帮助&#xff0c;或者你只是想表…

可看见车辆行人的高清实时视频第5辑

我们在《看见车辆行人的高清实时视频第4辑》分享了10处可看见车辆行人的实时动态高清视频。 现在我们又整理10处为你分享可看见车辆行人的实时动态高清视频&#xff0c;一共有50个摄像头数据&#xff0c;这些视频来自公开的高清摄像头实时直播画面。 我们在文末为你分享了这些…

制造业如何从0-1实现信息化建设?

深度长文&#xff0c;4000 字&#xff0c;融合了众多企业的实践经验和行业观点&#xff0c;一文讲清制造业信息化建设的路径&#xff0c;心急的小伙伴可以先看目录&#xff1a; 关于定义 —— 制造业信息化建设是什么&#xff1f;关于价值 —— 为什么制造业要进行信息化建设…

【C++】精妙的哈希算法

&#x1f680;个人主页&#xff1a;小羊 &#x1f680;所属专栏&#xff1a;C 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 一、哈希结构1、哈希概念2、哈希函数3、哈希冲突3.1 闭散列3.2 开散列 4、完整代码 一、哈希结构 1、哈希概念 A…

漏扫工具Appscan使用(非常详细)从零基础入门到精通,看完这一篇就够了。

1、简介 AppScan是一款商业化的web安全扫描工具&#xff0c;web扫描领域十分受欢迎 2、具体使用规则 1、常用界面 新建扫描文件 选择扫描 对于第一种扫描方式&#xff1a; 设置url和服务器 登录管理&#xff1a;对于需要登陆的页面&#xff08;这种方法不允许有验证码&#…

人工智能AI与机器学习ML基础入门

小学生都能看懂的人工智能入门书籍 第一章 入门简介 TensorFlow 入门 如果你想入门人工智能&#xff08;AI&#xff09;&#xff1f;机器学习&#xff08;ML&#xff09;和深度学习是很好的起点。不过&#xff0c;一开始接触这些概念时&#xff0c;可能会被各种选项和新术语搞…

关于Spring Framework路径遍历漏洞(CVE-2024-38816)的预警提示和修复方案

一、漏洞详情 Spring Framework是一个Java应用程序框架&#xff0c;旨在提供高效且可扩展的开发环境。 近日&#xff0c;监测到Spring Framework中修复了一个路径遍历漏洞&#xff08;CVE-2024-38816&#xff09;。Spring Framework受影响版本中&#xff0c;使用WebMvc.fn 或…

MyBatisCodeHelperPro一直用教程

qq群&#xff1a;984518344 不懂请留言&#xff01;&#xff01;&#xff01; &#xff08;有能力请请支持正版&#xff01;&#xff01;&#xff09; &#xff08;仅供学习交流&#xff0c;严禁用于商业用途&#xff0c;请于24小时内删除&#xff01;&#xff01;&#xff09…

使用标注工具并跑通官方yolov8分割segment自己的数据集

1.下载标注工具用于打标签 使用标注工具&#xff0c;后面会用到智能标注 点击 创建AI多边形后命令行就自动下载对应的模型 单机要选中的图像就行&#xff0c;就可以智能选中&#xff0c;双击设置标签 依次标注所有图片 &#xff0c;最后保存成json格式的文件 2.使用labelme2y…

Nuxt.js 应用中的 modules:before 事件钩子详解

title: Nuxt.js 应用中的 modules:before 事件钩子详解 date: 2024/10/15 updated: 2024/10/15 author: cmdragon excerpt: modules:before 是 Nuxt.js 中一个重要的生命周期钩子,在 Nuxt 应用初始化期间被触发。该钩子允许开发者在安装用户定义的模块之前执行某些操作,如…

交通目标识别数据集YOLO 模型 ui界面✓图片数量15000,xml和txt标签都有 11类 交通道路车辆行人红黄绿数据集 红绿灯数据集 交通信号数据集

YOLO交通目标识别 数据集 模型 ui界面 ✓图片数量15000&#xff0c;xml和txt标签都有&#xff1b; ✓class&#xff1a;biker&#xff0c;car&#xff0c;pedestrian&#xff0c;trafficLight&#xff0c;trafficLight-Green&#xff0c;trafficLight-GreenLeft&#xff0c; tr…

WPF中MVVM的应用举例

WPF&#xff08;Windows Presentation Foundation&#xff09;是微软开发的用于创建用户界面的框架&#xff0c;而MVVM&#xff08;Model-View-ViewModel&#xff09;模式是一种分离前端UI逻辑与后台业务逻辑的方法。在WPF中使用MVVM模式可以提高代码的可维护性、可测试性和可扩…

Vant 日期时间组件拓展

基于 "vant": "^4.8.3", 效果图 <template><!-- 弹出层 --><van-popupv-model:show"isPicker"position"bottom"><van-pickerref"picker":title"title"v-model"selectedValues"…

匿名管道和命名管道

目录 管道 pipe创建一个管道 让子进程写入&#xff0c;父进程读取 如何把消息发送/写入给父进程 父进程该怎么读取呢 管道本质 结论&#xff1a;管道的特征&#xff1a; 测试管道大小 写端退了&#xff0c;测试结果 测试子进程一直写&#xff0c;父进程读一会就退出 …

PAT甲级-1076 Forwards on Weibo

题目 题目大意 已知微博上粉丝都可能会转发自己所关注的人的动态&#xff0c;给定总人数n和层数l&#xff0c;和每个id关注的人数及所关注人的id。要求查询一组用户的潜在转发量&#xff0c;粉丝层级不能超过l。 思路 求潜在转发量&#xff0c;就是一层一层的找粉丝数&#…

【已知当前表字段名注入】

一、通配符注入 like 测试注入 usernameadmin&passwordadmin 提示username or password error输入单引号闭合测试 这里用or防止admin字段不存在数据库中&#xff0c;如果admin不存在用and连接admin不为真&#xff0c;username的逻辑还是没绕过&#xff0c;用or就算我们前面…

嵌入式Linux开发板配置静态IP

嵌入式Linux开发板配置静态IP Chapter1 嵌入式Linux开发板配置静态IPChapter2 Linux命令之hwclock - 查询和设置硬件时钟 Chapter1 嵌入式Linux开发板配置静态IP 修改interfaces配置文件&#xff0c;普通用户interfaces文件权限只可读&#xff0c;首先切换到root权限。 sudo …