最简单可配置的多数据源dataSource"/>
最简单可配置的多数据源dataSource
场景
公司需要从数量不定,类型可能不同的第三方数据库读取数据。
需求
数据库信息需要动态配置(如从数据库读取),需要动态设置DataSource,且考虑到线程安全。
所以写死的多数据源满足不了。
下面代码已满足基本要求,便捷性自行扩展。
解释:ComRecord 它是个自定义的map。
数据源代码:
package com.tyl.localhis.dao;import com.tylm.basic.ComRecord;
import com.tylm.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();//数据库urldataSource.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类型,名称对应不上返回linkdlistsimpleJdbcCall.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;}@Overridepublic 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,修改为GBKif (!"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());}
牛逼,真他么想给自己点个赞。
更多推荐
最简单可配置的多数据源dataSource
发布评论