Spring Boot 多数据源配置(JPA)

目录

前言

前置环境

pom

yml

Entity

Dao

Config

Controller

演示


前言

一般一个系统至少有一个数据源,用来持久化业务数据以及查询。单个数据源的系统很常见,在 Spring Boot 框架下配置也很简单。在约定大于配置这个思想下,只需要在配置文件中简单配置下数据库连接信息就行了。

除了单数据源系统,在实际工作中,还会遇到多数据源系统。有可能是因为业务需要,以实际中做过的资产清查相关的项目为例,数据的存储分成了两个库,一个当前库和归档库,系统就需要配置两个数据源来满足业务需求。也有可能是技术架构,比如 MySQL 数据库使用了主从复制架构来实现读写分离,然后在应用层做分流,就需要配置主库和从库数据源,并在代码中决定使用哪个库进行数据库操作。

以下是Spring Boot JPA 多数据源的配置教程

前置环境

JDK8 + SringBoot2 + MySQL8

分别创建数据库 test1 test2

分别在两个数据库中创建 user 表

create table user (
    id int auto_increment primary key,
    username varchar(255),
    password varchar(255)
);

在test1.user 表中插入数据

insert into user(username, password) values('张三', '123456');

在test2.user 表中插入数据

insert into user(username, password) values('李四', '123456');

pom

    <dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</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></dependency><dependencies>

yml

server:port: 8888spring:datasource:primary:url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: rootpassword: mysqldriver-class-name: com.mysql.cj.jdbc.Driversecondary:url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=trueusername: rootpassword: mysqldriver-class-name: com.mysql.cj.jdbc.Driverjpa:primary:show-sql: trueproperties:hibernate:hbm2ddl:auto: updatedialect: org.hibernate.dialect.MySQL5InnoDBDialectsecondary:show-sql: trueproperties:hibernate:hbm2ddl:auto: updatedialect: org.hibernate.dialect.MySQL5InnoDBDialect

Entity

主库和从库的实体类需要放在不同的包下,以本文为例

主库的实体类包路径为:com.jpa.entity.primary

@Entity
@Table ( name = "user")
public class PrimaryUserEntity {private Integer id;private String username;private String password;@Id@GeneratedValue ( strategy = GenerationType.IDENTITY)@Column ( name = "id" )public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}@Basic@Column ( name = "username" )public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Basic@Column ( name = "password" )public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

从库的实体类包路径为:com.jpa.entity.secondary

@Entity
@Table ( name = "user")
public class SecondaryUserEntity {private Integer id;private String username;private String password;@Id@GeneratedValue ( strategy = GenerationType.IDENTITY)@Column ( name = "id" )public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}@Basic@Column ( name = "username" )public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Basic@Column ( name = "password" )public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}}

Dao

主库和从库的Dao需要放在不同的包下,以本文为例

主库的Dao包路径为:com.jpa.dao.primary

@Repository (value = IPrimaryUserDao.DAO_BEAN_NAME )
public interface IPrimaryUserDao extends JpaRepository<PrimaryUserEntity, Integer> {String DAO_BEAN_NAME = "primaryUserDao";
}

从库的Dao包路径为:com.jpa.dao.secondary

@Repository (value = ISecondaryUserDao.DAO_BEAN_NAME )
public interface ISecondaryUserDao extends JpaRepository<SecondaryUserEntity, Integer> {String DAO_BEAN_NAME = "secondaryUserDao";
}

Config

记得将类中的两个包路径修改成自己项目的包路径

REPOSITORY_PACKAGE

ENTITY_PACKAGE

主库数据源配置

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories (basePackages = PrimaryDatasourceAndJpaConfig.REPOSITORY_PACKAGE,entityManagerFactoryRef = "primaryEntityManagerFactory",transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryDatasourceAndJpaConfig {private static final String REPOSITORY_PACKAGE = "com.jpa.dao.primary";private static final String ENTITY_PACKAGE = "com.jpa.entity.primary";//--------------数据源配置-------------------/*** 扫描spring.datasource.primary开头的配置信息** @return 数据源配置信息*/@Primary@Bean(name = "primaryDataSourceProperties")@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSourceProperties dataSourceProperties() {return new DataSourceProperties();}/*** 取主库数据源对象** @param dataSourceProperties 注入名为primaryDataSourceProperties的bean* @return 数据源对象*/@Primary@Bean(name = "primaryDataSource")public DataSource dataSource(@Qualifier("primaryDataSourceProperties") DataSourceProperties dataSourceProperties) {return dataSourceProperties.initializeDataSourceBuilder().build();}/*** 扫描spring.jpa.primary开头的配置信息** @return jpa配置信息*/@Primary@Bean (name = "primaryJpaProperties")@ConfigurationProperties (prefix = "spring.jpa.primary")public JpaProperties jpaProperties() {return new JpaProperties();}/*** 获取主库实体管理工厂对象** @param primaryDataSource 注入名为primaryDataSource的数据源* @param jpaProperties     注入名为primaryJpaProperties的jpa配置信息* @param builder           注入EntityManagerFactoryBuilder* @return 实体管理工厂对象*/@Primary@Bean(name = "primaryEntityManagerFactory")public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(@Qualifier ("primaryDataSource") DataSource primaryDataSource,@Qualifier("primaryJpaProperties") JpaProperties jpaProperties,EntityManagerFactoryBuilder builder) {return builder// 设置数据源.dataSource(primaryDataSource)// 设置jpa配置.properties(jpaProperties.getProperties())// 设置实体包名.packages(ENTITY_PACKAGE)// 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源.persistenceUnit("primaryPersistenceUnit").build();}/*** 获取实体管理对象** @param factory 注入名为primaryEntityManagerFactory的bean* @return 实体管理对象*/@Primary@Bean(name = "primaryEntityManager")public EntityManager entityManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory factory) {return factory.createEntityManager();}/*** 获取主库事务管理对象** @param factory 注入名为primaryEntityManagerFactory的bean* @return 事务管理对象*/@Primary@Bean(name = "primaryTransactionManager")public JpaTransactionManager transactionManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory factory) {return new JpaTransactionManager(factory);}
}

从库数据源配置

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = SecondaryDatasourceAndJpaConfig.REPOSITORY_PACKAGE,entityManagerFactoryRef = "secondaryEntityManagerFactory",transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryDatasourceAndJpaConfig {static final String REPOSITORY_PACKAGE = "com.jpa.dao.secondary";static final String ENTITY_PACKAGE = "com.jpa.entity.secondary";//--------------数据源配置-------------------/*** 扫描spring.datasource.secondary开头的配置信息** @return 数据源配置信息*/@Bean(name = "secondaryDataSourceProperties")@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSourceProperties dataSourceProperties() {return new DataSourceProperties();}/*** 获取次数据源对象** @param dataSourceProperties 注入名为secondaryDataSourceProperties的bean* @return 数据源对象*/@Bean("secondaryDataSource")public DataSource dataSource(@Qualifier("secondaryDataSourceProperties") DataSourceProperties dataSourceProperties) {return dataSourceProperties.initializeDataSourceBuilder().build();}/*** 扫描spring.jpa.secondary** @return jpa配置信息*/@Bean(name = "secondaryJpaProperties")@ConfigurationProperties(prefix = "spring.jpa.secondary")public JpaProperties jpaProperties() {return new JpaProperties();}/*** 获取次库实体管理工厂对象** @param secondaryDataSource 注入名为secondaryDataSource的数据源* @param jpaProperties       注入名为secondaryJpaProperties的jpa配置信息* @param builder             注入EntityManagerFactoryBuilder* @return 实体管理工厂对象*/@Bean(name = "secondaryEntityManagerFactory")public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("secondaryDataSource") DataSource secondaryDataSource,@Qualifier("secondaryJpaProperties") JpaProperties jpaProperties,EntityManagerFactoryBuilder builder) {return builder// 设置数据源.dataSource(secondaryDataSource)// 设置jpa配置.properties(jpaProperties.getProperties())// 设置实体包名.packages(ENTITY_PACKAGE)// 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源.persistenceUnit("secondaryPersistenceUnit").build();}/*** 获取实体管理对象** @param factory 注入名为secondaryEntityManagerFactory的bean* @return 实体管理对象*/@Bean(name = "secondaryEntityManager")public EntityManager entityManager(@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory factory) {return factory.createEntityManager();}/*** 获取事务管理对象** @param factory 注入名为secondaryEntityManagerFactory的bean* @return 事务管理对象*/@Bean(name = "secondaryTransactionManager")public JpaTransactionManager transactionManager(@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory factory) {return new JpaTransactionManager(factory);}
}

Controller

主库

@RestController
@RequestMapping(value = "/primary")
public class PrimaryJpaController {@Resourceprivate IPrimaryUserDao primaryUserDao;@RequestMapping(value = "/findAll", method = RequestMethod.GET)public List<PrimaryUserEntity> findAll() {return primaryUserDao.findAll();}
}

从库

@RestController
@RequestMapping(value = "/secondary")
public class SecondaryJpaController{@Resourceprivate ISecondaryUserDao secondaryUserDao;@RequestMapping(value = "/findAll", method = RequestMethod.GET)public List<SecondaryUserEntity> findAll() {return secondaryUserDao.findAll();}
}

演示

请求 /primary/findAll

请求 /secondary/findAll

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue 中计算属性可以接收参数

代码中的value就是接收的参数 计算属性要接收参数要写在返回的时候 computed: {isButtonDisabled() {return (value) > {const num parseInt(value);return isNaN(num) || num < 0}},},//计算属性aaa(){return (value) >{写逻辑return 返回值}} 使用 <el-butto…

Python OpenCV 深入理解(二)

引言 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个用于计算机视觉的开源软件库。它提供了大量的图像处理和机器视觉功能&#xff0c;支持多种编程语言&#xff0c;其中Python接口因其易用性和快速原型设计能力而受到广泛欢迎。本文将详细介绍如何…

基于OMS构建OceanBase容灾双活架构的实践

在实际生产环境中&#xff0c;对于关键业务&#xff0c;往往会有容灾双活的需求。除了OceanBase提供的主备库能力&#xff0c;通过官方工具OMS也可以实现容灾双活架构。目前&#xff0c;通过OMS实现的双活架构仅支持OceanBase数据库之间的数据同步。 要通过OMS实现双活架构&am…

合宙LuatOS开发板Core_Air780EP使用说明

Core-Air780EP 开发板是合宙通信推出的基于 Air780EP 模组所开发的&#xff0c; 包含电源&#xff0c;SIM卡&#xff0c;USB&#xff0c;天线&#xff0c;音频等必要功能的最小硬件系统。 以方便用户在设计前期对 Air780EP模块进行性能评估&#xff0c;功能调试&#xff0c;软…

快速学习GO语言总结

干货分享&#xff0c;感谢您的阅读&#xff01;备注&#xff1a;本博客将自己初步学习GO的总结进行分享&#xff0c;希望大家通过本博客可以在短时间内快速掌握GO的基本程序编码能力&#xff0c;如有错误请留言指正&#xff0c;谢谢&#xff01; 一、初步了解Go语言 &#xf…

基于约束大于规范的想法,封装缓存组件

架构&#xff1f;何谓架构&#xff1f;好像并没有一个准确的概念。以前我觉得架构就是搭出一套完美的框架&#xff0c;可以让其他开发人员减少不必要的代码开发量&#xff1b;可以完美地实现高内聚低耦合的准则;可以尽可能地实现用最少的硬件资源&#xff0c;实现最高的程序效率…

职业院校如何建设人工智能实训室

随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;越来越多的职业院校开始意识到培养具备AI技能的人才的重要性。为了让学生能够在实践中学习&#xff0c;职业院校需要建立能够支持实际操作的人工智能实训室。本文将探讨职业院校应该如何规划和建设一个高效且…

大模型产品经理学习路线,2024最新,从零基础入门到精通,非常详细收藏我这一篇

随着人工智能技术的发展&#xff0c;尤其是大模型&#xff08;Large Model&#xff09;的兴起&#xff0c;越来越多的企业开始重视这一领域的投入。作为大模型产品经理&#xff0c;你需要具备一系列跨学科的知识和技能&#xff0c;以便有效地推动产品的开发、优化和市场化。以下…

《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 09部署OSPF

本章的目的是帮助网络工程师确定网络的理想 OSPF 配置。本章将回答以下问题 应何时在数据中使用OSPF ?配置 OSPF 的关键设计原则是什么?OSPFv2 和 OSPFv3 之间有什么区别&#xff0c;应如何使用?如何在路由协议栈中配置 OSPF ?如何在服务器上配置 OSPF&#xff0c;例如为容…

Electron 项目实战 03: 实现一个截图功能

实现效果 实现思路 创建两个window&#xff0c;一个叫mainWindow&#xff0c;一个叫cutWindowmainWindow&#xff1a;主界面用来展示截图结果cutWindow&#xff1a;截图窗口&#xff0c;加载截图页面和截图交互逻辑mainWindow 页面点击截图&#xff0c;让cutWIndow 来实现具体…

‌智慧公厕:城市文明的智慧新篇章‌@卓振思众

在日新月异的城市化进程中&#xff0c;公共设施的智能化升级已成为不可逆转的趋势。其中&#xff0c;智慧公厕作为城市智慧化建设的重要组成部分&#xff0c;正悄然改变着我们的生活。智慧公厕&#xff0c;这一融合了物联网、大数据、云计算等现代信息技术的创新产物&#xff0…

Django Admin管理后台导入CSV

修改管理模型&#xff0c;代码如下&#xff1a; class CsvImportForm(forms.Form):csv_file forms.FileField() admin.register(Hero) class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):...change_list_template "entities/heroes_changelist.html"def get_url…

Opencv中的直方图(2)计算图像的直方图函数calcHist()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算一组数组的直方图。 函数 cv::calcHist 计算一个或多个数组的直方图。用于递增直方图bin的元组的元素是从相同位置的相应输入数组中获取的。…

MATLAB中cond函数用法

目录 语法 说明 示例 矩阵的条件数 1-范数条件数 cond函数的功能是返回逆运算的条件数。 语法 C cond(A) C cond(A,p) 说明 C cond(A) 返回 2-范数逆运算的条件数&#xff0c;等于 A 的最大奇异值与最小奇异值之比。 C cond(A,p) 返回 p-范数条件数&#xff0c;其中…

虚幻地形高度图生成及测试

虚幻地形高度图生成及测试 虚幻引擎地形系统将高度数据存储在高度图中&#xff0c;这是一个灰阶图像&#xff0c;使用黑白色值来存储地貌高程。在高度图中&#xff0c;纯黑色值表示最低点&#xff0c;纯白色值表示最高点。支持16位灰阶PNG、8位灰阶r8及16位灰阶r16格式。 本文…

C++设计模式——Template Method模板方法模式

一&#xff0c;模板方法模式的定义 模板方法模式是一种行为型设计模式&#xff0c;它先定义了一个算法的大致框架&#xff0c;然后将算法的具体实现步骤分解到多个子类中。 模板方法模式为算法设计了一个抽象的模板&#xff0c;算法的具体代码细节由子类来实现&#xff0c;从…

springboot高校实验室教学管理系统的设计和实现

基于springbootvue高校实验室教学管理系统的设计和实现(源码L文ppt)4-045 4 系统总体设计 此次高校实验室教学管理系统通过springboot框架。springboot适合快速构建Web应用。springboot将B/S设计模式中的视图分成了View模块和Template模块两部分&#xff0c;将动态的逻辑处理…

传统CV算法——基于opencv的答题卡识别判卷系统

基于OpenCV的答题卡识别系统&#xff0c;其主要功能是自动读取并评分答题卡上的选择题答案。系统通过图像处理和计算机视觉技术&#xff0c;自动化地完成了从读取图像到输出成绩的整个流程。下面是该系统的主要步骤和实现细节的概述&#xff1a; 1. 导入必要的库 系统首先导入…

亚信安全荣获“2024年网络安全优秀创新成果大赛”优胜奖

近日&#xff0c;由中央网信办网络安全协调局指导、中国网络安全产业联盟&#xff08;CCIA&#xff09;主办的“2024年网络安全优秀创新成果大赛”评选结果公布。亚信安全信舱ForCloud荣获“创新产品”优胜奖&#xff0c;亚信安全“宁波市政务信息化网络数据安全一体化指挥系统…

C语言 | Leetcode C语言题解之第392题判断子序列

题目&#xff1a; 题解&#xff1a; bool isSubsequence(char* s, char* t) {int n strlen(s), m strlen(t);int f[m 1][26];memset(f, 0, sizeof(f));for (int i 0; i < 26; i) {f[m][i] m;}for (int i m - 1; i > 0; i--) {for (int j 0; j < 26; j) {if (t…