背景

现在已有一个完整的项目,需要引入一个新的数据源,其实也就是分一些请求到从库上去

技术栈

springboot1.5 (哎,升不动啊)

思路

  1. 两个数据源,其中一个设置为主数据源
  2. 两个事物管理器,其中一个设置为主默认事物管理器
  3. 使用非主数据源时,一定要设置对应的事物管理器
  4. 利用 dao 下的不同包路径,不同路径下的对应 Repository 使用不同的数据源
@Service
@Transactional(transactionManager = "transactionManagerSecond", rollbackFor = Exception.class)
public class DashBoardService { }

启动日志

[timestamp=2020-10-13 21:09:19.317] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HikariCP pool "mysql-hikari-pool-1" is starting.
[timestamp=2020-10-13 21:09:19.584] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HikariCP连接池配置
连接池名称:"mysql-hikari-pool-1"
最小空闲连接数:1
最大连接数:20
连接超时时间:3000ms
空闲连接超时时间:600000ms
连接最长生命周期:1800000ms [timestamp=2020-10-13 21:09:19.628] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] Building JPA container EntityManagerFactory for persistence unit 'primaryPersistenceUnit'
[timestamp=2020-10-13 21:09:19.638] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000204: Processing PersistenceUnitInfo [
name: primaryPersistenceUnit
...]
[timestamp=2020-10-13 21:09:19.697] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000412: Hibernate Core {5.0.11.Final}
[timestamp=2020-10-13 21:09:19.698] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000206: hibernate.properties not found
[timestamp=2020-10-13 21:09:19.699] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000021: Bytecode provider name : javassist
[timestamp=2020-10-13 21:09:19.740] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
[timestamp=2020-10-13 21:09:19.904] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
[timestamp=2020-10-13 21:09:20.767] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] Initialized JPA EntityManagerFactory for persistence unit 'primaryPersistenceUnit'
[timestamp=2020-10-13 21:09:20.937] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HikariCP连接池配置
连接池名称:"mysql-hikari-pool-2"
最小空闲连接数:1
最大连接数:20
连接超时时间:3000ms
空闲连接超时时间:600000ms
连接最长生命周期:1800000ms [timestamp=2020-10-13 21:09:20.967] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] Building JPA container EntityManagerFactory for persistence unit 'secondPersistenceUnit'
[timestamp=2020-10-13 21:09:20.967] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000204: Processing PersistenceUnitInfo [
name: secondPersistenceUnit
...]
[timestamp=2020-10-13 21:09:21.036] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HikariCP pool "mysql-hikari-pool-2" is starting.
[timestamp=2020-10-13 21:09:21.113] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
[timestamp=2020-10-13 21:09:21.369] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] Initialized JPA EntityManagerFactory for persistence unit 'secondPersistenceUnit'
[timestamp=2020-10-13 21:09:21.834] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000397: Using ASTQueryTranslatorFactory
[timestamp=2020-10-13 21:09:26.616] [level=INFO] [tx_id=] [span_id=] [bu_id=JT_MW] [app_id=iflow] HHH000397: Using ASTQueryTranslatorFactory

重要

*在使用非主数据源时,一定要显式的指定对应使用管理器,不然连接池会耗尽的

*

dao层使用第二数据源, 用EntityManager

package com.daleyzou.multidatasource.dao.second;

import com.daleyzou.multidatasource.po.NodePo;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Repository; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List; /**
* @ClassName NodeNativeSQLDao
* @Description: 在dao层使用第二数据源, 用EntityManager, 需要指定对应的 unitName
* @Author dalelyzou
* @Date 2020/10/7
* @Version V1.0
**/
@Repository
@Slf4j
public class NodeNativeSQLDao { @PersistenceContext(unitName = "secondPersistenceUnit")
private EntityManager entityManager; /**
* 使用自定义SQL查询数据
*
* @param
* @return
* @author daleyzou
*/
public List<NodePo> getAll() {
StringBuilder sb = new StringBuilder();
sb.append("SELECT * from node");
SQLQuery sqlQuery = entityManager.createNativeQuery(sb.toString()).unwrap(SQLQuery.class);
org.hibernate.Query query = sqlQuery.setResultTransformer(Transformers.aliasToBean(NodePo.class));
return query.list();
}
}

对应的unitName是我们自己在数据源的 SecondConfig 里定义的

 @Bean(name = "entityManagerFactorySecond")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecond(EntityManagerFactoryBuilder builder) {
DataSourceConfig.logDS(secondDataSource);
return builder.dataSource(secondDataSource).properties(getVendorProperties(secondDataSource))
.packages("com.daleyzou.multidatasource.po").persistenceUnit("secondPersistenceUnit").build();
}

主要代码如下

DataSourceConfig

package com.daleyzou.multidatasource.config;

import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
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 javax.sql.DataSource; /**
* DataSourceConfig
* @description 数据源配置
* @author daleyzou
* @date 2020年10月12日 19:45
* @version 1.4.8
*/
@Configuration
@Slf4j
public class DataSourceConfig { /**
* 数据源配置对象
* Primary 表示默认的对象,Autowire可注入,不是默认的得明确名称注入
* @return
*/
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
} /**
* 数据源对象
* @return
*/
@Primary
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return primaryDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
} @Bean
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSourceProperties secondaryDataSourceProperties() {
return new DataSourceProperties();
} /**
* 第二个数据源
* @return
*/
@Bean(name = "secondDataSource")
@Qualifier("secondDataSource")
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSource secondaryDataSource() {
return secondaryDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
} /**
* 显示数据库连接池信息
*
* @param dataSource
*/
public static void logDS(DataSource dataSource) {
HikariDataSource hds = (HikariDataSource) dataSource;
String info = "\n\n\tHikariCP连接池配置\n\t连接池名称:" + hds.getPoolName() + "\n\t最小空闲连接数:" + hds.getMinimumIdle() + "\n\t最大连接数:" + hds
.getMaximumPoolSize() + "\n\t连接超时时间:" + hds.getConnectionTimeout() + "ms\n\t空闲连接超时时间:" + hds.getIdleTimeout()
+ "ms\n\t连接最长生命周期:" + hds.getMaxLifetime() + "ms\n";
log.info(info);
}
}

PrimaryConfig

package com.daleyzou.multidatasource.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map; /**
* PrimaryConfig
* @description 默认的主数据源
* @author daleyzou
* @date 2020年10月12日 19:46
* @version 1.4.8
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryPrimary", transactionManagerRef = "transactionManagerPrimary", basePackages = {
"com.daleyzou.multidatasource.dao.primary" })
public class PrimaryConfig { @Autowired
private JpaProperties jpaProperties; @Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource; @Primary
@Bean(name = "entityManagerPrimary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
} @Primary
@Bean(name = "entityManagerFactoryPrimary")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
DataSourceConfig.logDS(primaryDataSource);
return builder.dataSource(primaryDataSource).properties(getVendorProperties(primaryDataSource))
.packages("com.daleyzou.multidatasource.po").persistenceUnit("primaryPersistenceUnit").build();
} private Map<String, String> getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
} @Primary
@Bean(name = "transactionManagerPrimary")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}

SecondConfig

package com.daleyzou.multidatasource.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map; /**
* SecondConfig
* @description 第二数据源
* @author daleyzou
* @date 2020年10月12日 19:46
* @version 1.4.8
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
//实体管理
entityManagerFactoryRef = "entityManagerFactorySecond",
//事务管理
transactionManagerRef = "transactionManagerSecond",
//实体扫描,设置Repository所在位置
basePackages = { "com.daleyzou.multidatasource.dao.second" })
public class SecondConfig { @Autowired
private JpaProperties jpaProperties; @Autowired
@Qualifier("secondDataSource")
private DataSource secondDataSource; @Bean(name = "entityManagerSecond")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecond(builder).getObject().createEntityManager();
} @Bean(name = "entityManagerFactorySecond")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecond(EntityManagerFactoryBuilder builder) {
DataSourceConfig.logDS(secondDataSource);
return builder.dataSource(secondDataSource).properties(getVendorProperties(secondDataSource))
.packages("com.daleyzou.multidatasource.po").persistenceUnit("secondPersistenceUnit").build();
} private Map<String, String> getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
} @Bean(name = "transactionManagerSecond")
PlatformTransactionManager transactionManagerSecond(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecond(builder).getObject());
}
}

仓库代码

https://github.com/daleyzou/MultiDatasource

springboot1.5和jpa利用HikariCP实现多数据源的使用的更多相关文章

  1. SpringBoot31 整合SpringJDBC、整合MyBatis、利用AOP实现多数据源

    一.整合SpringJDBC 1  JDBC JDBC(Java Data Base Connectivity,Java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系数 ...

  2. 如何利用excel中的数据源制作数据地图

    关于这个问题,制作数据地图的方法已不新奇,总体来说有这么几类方案: 一类方案:直接在excel里制作 优势:个人小数据量应用较为方便简单 缺点:需要熟悉VBA,且更强大的功能对VBA水平要求较高 1. ...

  3. SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换

    SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换 本文转载至:http://exceptioneye.iteye.com/blog/1698064 Spri ...

  4. spring data jpa 利用@Query进行查询

    参照https://blog.csdn.net/yingxiake/article/details/51016234#reply https://blog.csdn.net/choushi300/ar ...

  5. Spring Boot 应用系列 1 -- Spring Boot 2 整合Spring Data JPA和Druid,双数据源

    最近Team开始尝试使用Spring Boot + Spring Data JPA作为数据层的解决方案,在网上逛了几圈之后发现大家并不待见JPA,理由是(1)MyBatis简单直观够用,(2)以Hib ...

  6. [spring jpa] 解决SimpleJpaRepository的多数据源配置问题

    前言 前段时间使用spring jpa做了一个项目,由于涉及到了多个数据库,因此需要进行多数据源的配置.网上找了很多的资料,尝试着配置,都以失败告终.之后通过断点最终完成了多数据源的配置.这篇博客主要 ...

  7. MFC利用ADO建立access数据源 ---包括访问带access密码与不带access密码两种方式)

    void CDlg_login::OnButton1() { CString c_user,c_password;m_user1.GetWindowText(c_user);m_password1.G ...

  8. java结合testng,利用mysql数据库做数据源的数据驱动实例

    上一篇我们介绍用如何用yaml结合testng做数据驱动,就又想来个数据库的参数化 备注:@DataProvider的返回值类型只能是Object[][]与Iterator<Object> ...

  9. 利用AbstractRoutingDataSource实现动态数据源切换

    需求:系统中要实现切换数据库(业务数据库和his数据库) 网上很多资料上有提到AbstractRoutingDataSource,大致是这么说的 在Spring 2.0.1中引入了AbstractRo ...

随机推荐

  1. day46:jQuery

    目录 1.jQuery初识 2.选择器 3.文本操作 4.class类值操作 5.css样式操作 6.值操作 7.注意点:button按钮提交form表单数据 8.jquery选择器补充 9.模态对话 ...

  2. 阿里面试:dubbo的服务引用过程

    点赞再看,养成习惯,微信搜一搜[三太子敖丙]关注这个喜欢写情怀的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系 ...

  3. Nginx(二): worker 进程处理逻辑-流程框架

    Nginx 启动起来之后,会有几个进程运行:1. master 进程接收用户命令并做出响应; 2. worker 进程负责处理各网络事件,并同时接收来自master的处理协调命令: master 主要 ...

  4. get、post请求方式在jmeter中使用步骤

    jmeter:性能测试工具,压测 一.jmeter工具测试接口时使用步骤: 1.测试计划右键--添加--Threads(Users)--线程组(线程数就是并发数) 2.线程组右键--Sampler-- ...

  5. 分布式系统监视zabbix讲解三之用户和用户组

    概述 Zabbix 中的所有用户都通过 Web 前端去访问 Zabbix 应用程序.并为每个用户分配唯一的登陆名和密码. 所有用户的密码都被加密并储存于 Zabbix 数据库中.用户不能使用其用户名和 ...

  6. openstack核心组件——cinder存储服务(11)

    一.cinder 介绍:   理解 Block Storage 操作系统获得存储空间的方式一般有两种: 通过某种协议(SAS,SCSI,SAN,iSCSI 等)挂接裸硬盘,然后分区.格式化.创建文件系 ...

  7. 突发!美商务部宣布封禁微信,TikTok——面对科技封锁,如何应对

    刚刚美国商务部忽然发布了这则新闻,为了回应特朗普2020年8月6号的行政令,称这些应用程序存在安全威胁. 禁令中称,自2020年9月20日起,美国政府将: 1 禁止通过美国在线移动应用程序商店分发或维 ...

  8. ribbon源码(1) 概述

    ribbon的核心功能是提供客户端在进行网络请求时负载均衡的能力.主要有以下几个模块: 负载均衡器模块 负载均衡器模块提供了负载均衡能力,详细参见ribbon源码之负载均衡器. 配置模块 配置模块管理 ...

  9. Laravel驱动管理类Manager的分析和使用

    Laravel驱动管理类Manager的分析和使用 第一部分 概念说明 第二部分 Illuminate\Support\Manager源码 第三部分 Manager类的使用 第一部分:概念解释 结合实 ...

  10. keras中的mask操作

    使用背景 最常见的一种情况, 在NLP问题的句子补全方法中, 按照一定的长度, 对句子进行填补和截取操作. 一般使用keras.preprocessing.sequence包中的pad_sequenc ...