最简单可配置的多数据源dataSource

3 篇文章 0 订阅
1 篇文章 0 订阅

场景

公司需要从数量不定,类型可能不同的第三方数据库读取数据。

需求

数据库信息需要动态配置(如从数据库读取),需要动态设置DataSource,且考虑到线程安全。

所以写死的多数据源满足不了。

下面代码已满足基本要求,便捷性自行扩展。

解释:ComRecord  它是个自定义的map。

数据源代码:

package com.tyl.localhis.dao;

import com.tyl.comm.basic.ComRecord;
import com.tyl.comm.util.StringUtils;
import com.tyl.localhis.dao.dto.ProcedureDto;
import com.tyl.localhis.entity.config.SyncConfigDb;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @description 通用访问数据库类,该类可实现动态多数据源,且线程安全
* @author tangyaliang
 * @time 2021/12/11 22:56
*/
@Service
public class ComDao {
    private final ThreadLocal<MyJdbcTemplate> local = new ThreadLocal<>();
    private final Map<String, HikariDataSource> map = new HashMap<>();
    private final MyJdbcTemplate template = new MyJdbcTemplate();
    /**
     * 没有默认数据源
     */
    public ComDao(){}
    /**
     * 支持配置默认数据源,一般用不上
     * @param dataSource 默认数据源
     */
    public ComDao(DataSource dataSource){
        template.setDataSource(dataSource);
        local.set(template);
    }
    /**
     * @param config 数据库链接配置,db_id,db_url,db_name,db_pwd
     * @description 根据不同数据库用户名切换DataSource
     * @author tangyaliang  线程安全
     * @time 2021/12/11 22:56
     */
    public void setDataSource(SyncConfigDb config) {
        HikariDataSource dataSource = map.get(config.getDbId());
        if (dataSource == null) {
            dataSource = new HikariDataSource();
            //数据库url
            dataSource.setJdbcUrl(config.getDbUrl());
            //数据库用户名
            dataSource.setUsername(config.getDbName());
            //数据库密码
            dataSource.setPassword(config.getDbPwd());
            if (!StringUtils.isEmpry(config.getDbDriverName())) {
                dataSource.setDriverClassName(config.getDbDriverName());
            }
            //DataSource放入map中,等待使用
            map.put(config.getDbId(), dataSource);
        }
        template.setDataSource(dataSource);
        local.set(template);
    }

    /**
     * 执行sql语句
     * @param sql sql
     * @return 结果集
     */
    public List<ComRecord> query(String sql) {
        return local.get().query(sql, new ComRowMapper(local.get().getDbEnCoding()));
    }
    /**
     * 调用存储过程返回结果集
     * 目前可以调用oracle游标结果集,mysql结果集,其他微测试
     * @return 结果集
     */
    public List<ComRecord> queryProcedureByRefcursor(ProcedureDto dto) {
        //参数名称不区分大小写
        local.get().setResultsMapCaseInsensitive(true);
        SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(local.get());
        //设置储存过程名称
        simpleJdbcCall.withProcedureName(dto.getProcedurName());
        //设置存储过程游标或数据集名称,如果参数名称与存储过程中out名称相对应则返回ComRowMapper类型,名称对应不上返回linkdlist
        simpleJdbcCall.returningResultSet(dto.getRefcursorName(), new ComRowMapper(local.get().getDbEnCoding()));
        //.returningResultSet("data", BeanPropertyRowMapper.newInstance(Clazz.class));Clazz.class可以直接转化为实体类型
        //设置输入参数
        Map<String, Object> map;
        if (dto.getInParames() == null || dto.getInParames().size() == 0) {
            map = simpleJdbcCall.execute(new HashMap<>(0));
        } else {
            map = simpleJdbcCall.execute(dto.getInParames());
        }
        return (List<ComRecord>) map.get(dto.getRefcursorName());
    }


    /**
    * @description 通用RowMapper,其他地方用不到,所以定义为成员内部类
    * @author tangyaliang
    * @time 2021/12/11
    */
    class ComRowMapper implements RowMapper {
        String charSet;
        public ComRowMapper(){
        }
        public ComRowMapper(String charSet){
            this.charSet = charSet;
        }
        @Override
        public ComRecord mapRow(ResultSet rs, int rowNum) throws SQLException {
            ComRecord record = new ComRecord();
            ResultSetMetaData red = rs.getMetaData();
            DefaultLobHandler handler = new DefaultLobHandler();
            String columnName, value;
            try {
                for (int i = 1; i <= red.getColumnCount(); i++) {
                    columnName = red.getColumnName(i);

                    if (red.getColumnTypeName(i).equalsIgnoreCase("CLOB")) {
                        value = handler.getClobAsString(rs, i);
                    } else {
                        value = rs.getString(i);
                    }
                    //如果数据库字符集不是GBK,修改为GBK
                    if (!"GBK".equalsIgnoreCase(charSet) && charSet != null) {
                        if (value == null) continue;
                        value = new String(value.getBytes(charSet), "GBK");
                    }
                    record.put(columnName, value);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return record;
        }
    }
}

测试代码:用的定时任务,一秒钟执行一次

    private final ComDao comDao;

    @Scheduled(cron = "0/1 * * * * ?")
    public void data1() {
        SyncConfigDb db = new SyncConfigDb();
        db.setDbId("COMM");
        db.setDbUrl("jdbc:oracle:thin:@192.168.1.115:1521:orcl");
        db.setDbName("COMM");
        db.setDbPwd("123");
        comDao.setDataSource(db);
        List<ComRecord> list = comDao.query("select * from tablename1");
        System.out.println("data1==" + list.size());
    }

    @Scheduled(cron = "0/1 * * * * ?")
    public void data2() {
        SyncConfigDb db = new SyncConfigDb();
        db.setDbId("TYL");
        db.setDbUrl("jdbc:oracle:thin:@192.168.1.115:1521:orcl");
        db.setDbName("TYL");
        db.setDbPwd("123");
        comDao.setDataSource(db);
        List<ComRecord> list = comDao.query("select * from tablename2");
        System.out.println("data2==" + list.size());
    }

牛逼,真他么想给自己点个赞。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Spring Boot项目中配置多数据源,可以使用Spring Boot提供的多数据源支持。以下是一个简单的示例: 首先在application.properties中配置数据源的相关信息: ``` # 数据源1 spring.datasource.url=jdbc:mysql://localhost/test1 spring.datasource.username=root spring.datasource.password=password1 spring.datasource.driver-class-name=com.mysql.jdbc.Driver # 数据源2 spring.datasource.secondary.url=jdbc:mysql://localhost/test2 spring.datasource.secondary.username=root spring.datasource.secondary.password=password2 spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver ``` 然后定义两个数据源配置类: ```java @Configuration @Primary @ConfigurationProperties("spring.datasource") public class DataSource1Config extends HikariDataSource { } @Configuration @ConfigurationProperties("spring.datasource.secondary") public class DataSource2Config extends HikariDataSource { } ``` 在这个示例中,我们使用了HikariCP作为连接池,分别定义了两个数据源配置类。其中,@Primary注解表示默认使用第一个数据源。 接下来,定义两个JdbcTemplate的实例: ```java @Bean(name = "jdbcTemplate1") public JdbcTemplate jdbcTemplate1(@Qualifier("dataSource1") DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean(name = "jdbcTemplate2") public JdbcTemplate jdbcTemplate2(@Qualifier("dataSource2") DataSource dataSource) { return new JdbcTemplate(dataSource); } ``` 在这个示例中,我们使用了@Qualifier注解来指定要使用的数据源。 最后,在需要访问不同数据源的地方注入相应的JdbcTemplate即可,例如: ```java @Autowired @Qualifier("jdbcTemplate1") private JdbcTemplate jdbcTemplate1; @Autowired @Qualifier("jdbcTemplate2") private JdbcTemplate jdbcTemplate2; ``` 在实际使用中,我们可以根据需要自由切换数据源,以访问不同的数据库
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值