当前位置: 首页 > news >正文

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 数据仓库技术选型方案文档
  • 语言桥梁:探索全球最受欢迎的翻译工具,让理解更简单
  • Nginx 负载均衡+高可用 集群部署(Keepalived+LVS DR模式)
  • 【WPF动画】
  • 内存管理(三)--Linux CMA内存使用
  • 巧用xrename批量重命名下载的影视文件
  • SQL-函数
  • Open3D 基于曲率大小的特征点提取
  • 微信小程序中如何监听元素进入目标元素
  • stm32F103 串口2 中断 无法接收指定字符串 [已解决]
  • 用idea写Spark程序时,想要在控制台打印日志?
  • class 6: vue.js 3 组件化开发
  • 微服务--Nacos配置管理
  • axios返回的是promise对象如何处理?
  • Mysql高阶语句(1)
  • 2017年终总结、随想
  • Android 架构优化~MVP 架构改造
  • axios 和 cookie 的那些事
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • Java多态
  • php ci框架整合银盛支付
  • php中curl和soap方式请求服务超时问题
  • React16时代,该用什么姿势写 React ?
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • 从伪并行的 Python 多线程说起
  • 搭建gitbook 和 访问权限认证
  • 聚类分析——Kmeans
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 排序算法学习笔记
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #QT项目实战(天气预报)
  • $refs 、$nextTic、动态组件、name的使用
  • (¥1011)-(一千零一拾一元整)输出
  • (2)空速传感器
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (二)Kafka离线安装 - Zookeeper下载及安装
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (自用)gtest单元测试
  • .NET 反射 Reflect
  • .net 受管制代码
  • .netcore 获取appsettings
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .net通用权限框架B/S (三)--MODEL层(2)
  • /dev/sda2 is mounted; will not make a filesystem here!
  • ??myeclipse+tomcat
  • @Autowired标签与 @Resource标签 的区别
  • @Autowired自动装配
  • @RequestBody与@RequestParam