代码编织梦想

一、前言

多数据源的配置,是一个相对比较常见的需求。

什么是数据源?数据源就是javax.sql.DataSource,所有实现了这个接口的DataSource就叫做数据源,现在比较常用阿里巴巴的DruidDataSource,支持监控多数据源下的sql运行状况,便于以此实现以sql为核心的应用系统,比如BI报表系统、BI工具、ETL工具等。而这些场景下的业务sql通常是属于动态数据源,它们的操作对象来自于不同的数据库类型,或不同的数据库实例,通常被存放在某个业务表中,还可能需要被新增、删除和修改,因而我们不能像使用Mybatis那样,预先定义好要执行的所有sql,然后放在Mybatis的mapper配置文件中,这种Jdbc操作方式就显得不恰当,换用spring-jdbc的JdbcTemplate刚好可以完美地解决这个问题。

二、实现思路

2.1 配置数据源属性

这里选用DruidDataSource作为我们的业务数据源,一般在application.properties中为其配置各项Druid连接池属性,如下:

2.2 自定义业务数据源Bean

实现自己的DruidDataSource,加载上面的Druid数据源配置,初始化DruidDataSource实例,以线程安全的方式缓存在一Map<String, DruidDataSource>中,并提供获取数据源和关闭数据源的方法。如下:

package com.cjia.common.jdbc;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.StringUtils;
import com.cjia.common.exception.SourceException;
import com.cjia.model.SqlDBConfig;
import com.cjia.utils.MD5Util;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class JdbcDataSource extends DruidDataSource {

    @Value("${spring.datasource.type}")
    private String type;

    @Value("${source.max-active:10}")
    private int maxActive;

    @Value("${source.initial-size:5}")
    private int initialSize;

    @Value("${source.min-idle:3}")
    private int minIdle;

    @Value("${source.max-wait:30000}")
    private int maxWait;

    @Value("${spring.datasource.druid.time-between-eviction-runs-millis}")
    private int timeBetweenEvictionRunsMillis;

    @Value("${spring.datasource.druid.min-evictable-idle-time-millis}")
    private int minEvictableIdleTimeMillis;

    @Value("${spring.datasource.druid.test-while-idle}")
    private boolean testWhileIdle;

    @Value("${spring.datasource.druid.test-on-borrow}")
    private boolean testOnBorrow;

    @Value("${spring.datasource.druid.test-on-return}")
    private boolean testOnReturn;

    @Value("${spring.datasource.druid.filters}")
    private String filters;

    @Value("${source.break-after-acquire-failure:true}")
    private boolean breakAfterAcquireFailure;

    @Value("${source.connection-error-retry-attempts:0}")
    private int connectionErrorRetryAttempts;

    private static volatile Map<String, DruidDataSource> map = new HashMap<>();

    public synchronized void removeDatasource(String jdbcUrl, String username, String password) {
        String key = getKey(jdbcUrl, username, password);
        if (map.containsKey(key)) {
            map.remove(key);
        }
    }

    public synchronized DruidDataSource getDataSource(SqlDBConfig sqlDBConfig) throws SourceException {
    	String jdbcUrl = sqlDBConfig.getUrl();
    	String username = sqlDBConfig.getUsername();
    	String password = sqlDBConfig.getPassword();
    	String key = getKey(jdbcUrl, username, password);
        if (!map.containsKey(key) || null == map.get(key)) {
            DruidDataSource instance = new JdbcDataSource();
            String className = null;
            try {
                className = DriverManager.getDriver(jdbcUrl.trim()).getClass().getName();
            } catch (SQLException e) {
            }
            if (StringUtils.isEmpty(className)) {
            	throw new SourceException("Driver Class Not null: DbId=" + sqlDBConfig.getDbId());
            } else {
                instance.setDriverClassName(className);
            }
            instance.setUrl(jdbcUrl.trim());
            instance.setUsername(username);
            instance.setPassword(password);
            instance.setInitialSize(initialSize);
            instance.setMinIdle(minIdle);
            instance.setMaxActive(maxActive);
            instance.setMaxWait(maxWait);
            instance.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            instance.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            instance.setTestWhileIdle(false);
            instance.setTestOnBorrow(testOnBorrow);
            instance.setTestOnReturn(testOnReturn);
            try {
				instance.setFilters(filters);
			} catch (SQLException ex) {
				log.error("druid configuration initialization filter", ex);
			}
            instance.setConnectionErrorRetryAttempts(connectionErrorRetryAttempts);
            instance.setBreakAfterAcquireFailure(breakAfterAcquireFailure);

            try {
                instance.init();
            } catch (Exception e) {
                log.error("Exception during pool initialization", e);
                throw new SourceException(e.getMessage());
            }
            map.put(key, instance);
        }
        return map.get(key);
    }

    private String getKey(String jdbcUrl, String username, String password) {
        StringBuilder sb = new StringBuilder();
        if (!StringUtils.isEmpty(username)) {
            sb.append(username);
        }
        if (!StringUtils.isEmpty(password)) {
            sb.append(":").append(password);
        }
        sb.append("@").append(jdbcUrl.trim());
        return MD5Util.md5(sb.toString(), MD5Util.SEC_KEY);
    }
}

2.3 动态构造JdbcTemplate

首先,注入上一步自定义的业务数据源JdbcDataSource,接着,JdbcTemplate提供了传入DataSource的构造方式,获取到JdbcTemplate对象后,调用它丰富的API执行业务sql,如下:

// 获取初始化后的druid数据源,SqlDBConfig存放了jdbcUrl、username、password
DruidDataSource dataSource = jdbcDataSource.getDataSource(sqlDBConfig);
List<Map<String, Object>> result = new JdbcTemplate(dataSource).queryForList(sql, paramArgs);

以上。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/songzehao/article/details/100548930

spring jdbctemplate配置多数据源_演员赵诗绎的博客-爱代码爱编程

spring jdbctemplate配置多数据源        其实现在使用spring jdbctemplate与数据库交互已经有点low了,现在主流都是mybatis,但是遇到了就分享一下吧,spring jdbctemplate是怎么配置多数据源于调用的呢?         一、所搭建的项目为maven工程,pom.xml如下

jdbctemplate的数据源配置_宝石男孩的博客-爱代码爱编程_jdbctemplate配置数据源

import org.junit.Test; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class JDBCTemplate {

<转>spring aop根据jdbctemplate方法名动态设置数据源_iteye_5562的博客-爱代码爱编程

转载: Spring AOP根据JdbcTemplate方法名动态设置数据源 http://blog.csdn.net/yubaoma2014/article/details/12427885作者: yubaoma2014   有删节.   目的:  1. 配置多个数据源 2. 根据不同的数据源执行不同的数据操作方法

spring aop根据jdbctemplate方法名动态设置数据源-爱代码爱编程

为什么80%的码农都做不了架构师?>>>    说明:现在的场景是,采用MySQL Replication的方式在两台不同服务器部署并配置主从(Master-Slave)复制; 并需要程序上的数据操作方法访问不同的数据库,比如,update*方法访问主数据库服务器,query*方法访问从数据库服务器,从而减轻读

关于jdbctemplate动态切换数据库-爱代码爱编程

背景:项目中有一个需求是要根据DB的配置重新编译存储过程,但是要执行多个数据库的存储过程。因为数据库很多(大概10个左右),不想使用切换数据源的方式去实现。故有此文章来记录遇到的问题和解决过程。 技术:springboot

JdbcTemple 多数据源切换-爱代码爱编程

基于上一篇文章《Springboot Mybatis结合AOP做多数据源切换》扩展,多数据源结合JdbcTemple做数据源切换,这个可以不用做切面,可以初始化的时候就直接绑定数据源 1 修改 DataSourceConfig.java文件 加上 @Qualifier 这个注解 @Bean @Qualifier("master")

springboot JdbcTemplate配置多数据源, 使用 druid 连接池-爱代码爱编程

1.导入pom依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <

springboot动态数据源切换-爱代码爱编程

1,通过jdbc的方式动态切换数据源,实现既关即停,即开即用 @Component @Slf4j public class MySqlConfiguration { /** * mysql数据源 */ private Map<String, HikariDataSource> mySqlDataSource

Java基础之《JdbcTemplate多数据源配置和事务管理》-爱代码爱编程

1、DataSourceConfig.java package cn.xxx.coupon.pay.config; import javax.sql.DataSource; import org.springframework.boot.context.properties.ConfigurationProperties; import org.sp

jpa和jdbctemplate类的后期动态多数据源实现java源码_weixin_42183500的博客-爱代码爱编程

jpa和jdbcTemplate类都使用的是DataSource作为数据源,它只是一个接口类,主要就是对调用方提供了: public Connection getConnection(); 这样一个核心函数,返回一个标准的java.sql的连接对象Connection,以供给jpa或jdbcTemplate类使用来操作数据库表。 所以实现原理很简单,

jdbc连接池&jdbctemplate-爱代码爱编程

基本内容 1. 数据库连接池 - c3p0 - druid 3. Spring JDBC : JDBC Template 数据库连接池 1. 概念:其实就是一个容器(集合),存放数据库连接的容器。 当

【java多数据源实现教程】实现动态数据源、多数据源切换方式-爱代码爱编程

前言 本文为 【Java多数据源实现教程】 相关知识,由于自己最近在做导师的项目的时候需要使用这种技术,于是自学了相关技术原理与实现,并将其整理如下,具体包含:多数据源的典型使用场景(包含业务复杂场景、读写分离场景),多数

手动创建druiddatasource失败后死循环以及程序卡住的问题_druid failfast-爱代码爱编程

druid的版本:1.1.20 这个问题在druid的github源码上一直是个open的issue,见3488和3357等 druid的配置,注意timeBetweenEvictionRunsMillis参数,这是造成

springboot 之 jdbc 多数据源实现-爱代码爱编程

简介 Springboot 中使用 JdbcTemplate 实现多数据源比较简单。查看 JdbcTemplate 源码;可以发现 JdbcTemplate 提供了传入 DataSource 的方式构建不同的 JdbcTemplate 实例。通过该方式就可以实现多数据源。 public JdbcTemplate() { } public J