springboot1.5和jpa利用HikariCP实现多数据源的使用
背景
现在已有一个完整的项目,需要引入一个新的数据源,其实也就是分一些请求到从库上去
技术栈
springboot1.5 (哎,升不动啊)
思路
- 两个数据源,其中一个设置为主数据源
 - 两个事物管理器,其中一个设置为主默认事物管理器
 - 使用非主数据源时,一定要设置对应的事物管理器
 - 利用 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实现多数据源的使用的更多相关文章
- SpringBoot31 整合SpringJDBC、整合MyBatis、利用AOP实现多数据源
		
一.整合SpringJDBC 1 JDBC JDBC(Java Data Base Connectivity,Java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系数 ...
 - 如何利用excel中的数据源制作数据地图
		
关于这个问题,制作数据地图的方法已不新奇,总体来说有这么几类方案: 一类方案:直接在excel里制作 优势:个人小数据量应用较为方便简单 缺点:需要熟悉VBA,且更强大的功能对VBA水平要求较高 1. ...
 - SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换
		
SpringMVC 利用AbstractRoutingDataSource实现动态数据源切换 本文转载至:http://exceptioneye.iteye.com/blog/1698064 Spri ...
 - spring data jpa 利用@Query进行查询
		
参照https://blog.csdn.net/yingxiake/article/details/51016234#reply https://blog.csdn.net/choushi300/ar ...
 - Spring Boot 应用系列 1 -- Spring Boot 2 整合Spring Data JPA和Druid,双数据源
		
最近Team开始尝试使用Spring Boot + Spring Data JPA作为数据层的解决方案,在网上逛了几圈之后发现大家并不待见JPA,理由是(1)MyBatis简单直观够用,(2)以Hib ...
 - [spring jpa] 解决SimpleJpaRepository的多数据源配置问题
		
前言 前段时间使用spring jpa做了一个项目,由于涉及到了多个数据库,因此需要进行多数据源的配置.网上找了很多的资料,尝试着配置,都以失败告终.之后通过断点最终完成了多数据源的配置.这篇博客主要 ...
 - MFC利用ADO建立access数据源 ---包括访问带access密码与不带access密码两种方式)
		
void CDlg_login::OnButton1() { CString c_user,c_password;m_user1.GetWindowText(c_user);m_password1.G ...
 - java结合testng,利用mysql数据库做数据源的数据驱动实例
		
上一篇我们介绍用如何用yaml结合testng做数据驱动,就又想来个数据库的参数化 备注:@DataProvider的返回值类型只能是Object[][]与Iterator<Object> ...
 - 利用AbstractRoutingDataSource实现动态数据源切换
		
需求:系统中要实现切换数据库(业务数据库和his数据库) 网上很多资料上有提到AbstractRoutingDataSource,大致是这么说的 在Spring 2.0.1中引入了AbstractRo ...
 
随机推荐
- Spring JPA 查询创建
			
Spring JPA 查询创建 这是JPA内容的核心部分,可以收藏用作参阅文档. 1. 查询转化和关键字 例:一个JPA查询的转化 public interface UserRepository ex ...
 - PHP的八个魔术常量
			
1. 什么魔术常量 预定义常量:预定义常量就是PHP内置的常量,预先定义好的 PHP有很多预定义常量,比如:PHP_VERSION(版本号).PHP_OS(操作系统). 这些普通的预定义常量在程序中的 ...
 - Git 实用基础(配置,建库,提交,推送 GitHub)
			
Git 实用基础(配置,建库,提交,推送 GitHub) SVN ? Git ? 目前市面上主流的版本控制系统就是 SVN 和 Git . 两者的区别简单通俗地说就是,版本数据是否有在本地. 如果觉得 ...
 - (课堂笔记)第三章:F5 LTM 负载均衡理论
			
BIG-IP LTM负载均衡理论 ------F5 BIG-IP LTM负载均衡策略---------- 1.1 LTM VS工作模式F5 BIG-IP LTM的内部对于数据包的处理方式,即是VS的工 ...
 - 猜数字 python 3
			
随机选取一个1-100的整数 通过5次机会猜整数 会提醒猜大或者猜小 当猜对或者已经猜过5次后结束游戏
 - pytest文档3-pytest+Allure+jenkins+邮箱发送
			
前言: 虽然网上有很多邮件配置的文章,但还是想自己写一下配置的过程,因为在中间也碰到了不同坑.按照这个文档配置的话,99%都可以成功. 一.jenkins 配置邮箱 1.打开jenkins后进入点 ...
 - turtle空间坐标系
			
利用空间坐标改变行进 以海龟的角度来看,无论往那个方向运行,都叫正方向 turtle.fd向海龟的正前方运行,turtle.bk向反方向运行
 - JAVA之代理2CGLib
			
对于CGLib的代理目前还是知道如何使用,以及理论上它的原理,到源码上的理解还没到位 https://www.jianshu.com/p/9a61af393e41?from=timeline& ...
 - 龙芯3a4000办公机安装软件及美化记录
			
1.硬件平台: CPU:龙芯3a4000 Linux内核版本:4.19.90-1.lns7.2.mips64el 操作系统:Debian 10(buster) 使用过龙芯3a3000和3a4000两款 ...
 - Spring学习(八)AOP详解
			
文章更新时间:2020/04/06 一.一个例子 在上面的例子中,包租婆的核心业务就是签合同,收房租,那么这就够了,灰色框起来的部分都是重复且边缘的事,交给中介商就好了,这就是 AOP 的一个思想:让 ...