通用mapper 集成多数据源

这篇博客介绍了如何在Spring Boot应用中集成通用Mapper实现双数据源配置,包括一个动态数据源和一个非动态数据源。内容涵盖动态数据源的配置以及业务场景中的核心代码实现,适合初学者参考学习。

通用mapper集成双数据源

一个动态数据源(多数据源动态切换) 一个非动态数据源

非动态

/**
 * 主数据源
 * 注意,要支持tk-mybatis扩展中间件,需要用tk.mybatis.spring.annotation.MapperScan注解
 */
@Configuration
@MapperScan(basePackages = {"com.company.push.push.**.mapper"}, sqlSessionTemplateRef = "userSqlSessionTemplate")
public class PushMybatisConfig {
    @Value("${push.mybatis.mapperLocations}")
    private String mainMapper;

    @Bean(name = "userDataSource")
    @Primary //必须加此注解,不然报错,下一个类则不需要添加
    @ConfigurationProperties(prefix = "push.datasource") //prefix值必须是application.properteis中对应属性的前缀
	public DataSource userDataSource() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 配置事务管理器
     *
     * @param dataSource
     * @return
     */
    @Bean(name = "masterTransactionManger")
    @Primary
    public DataSourceTransactionManager masterTransactionManger(@Qualifier("userDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    @Primary
    public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setVfs(SpringBootVFS.class);
        bean.setTypeAliasesPackage("com.companyPush");
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            bean.setMapperLocations(resolver.getResources(mainMapper));
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Bean
    @Primary
    public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
        // 使用上面配置的Factory
        return template;
    }

    @Bean(name = "mainJdbcTemplate")
    public JdbcTemplate mainJdbcTemplate(@Qualifier("userDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

配置 多数据源(动态切换多数据源)

/**
 *
 *主类
 */
@Configuration
@MapperScan(basePackages = {"com.company.push.yewu.**.mapper"}, sqlSessionTemplateRef = "yewuSqlSessionTemplate")
public class DataSourceConfig {
	
	@Value("${yewu.mybatis.mapperLocations}")
	private String yewuMapper;
	/**
	 * 配置默认数据源
	 * @return
	 */
	@Bean
	@ConfigurationProperties(prefix = "yewu.datasource")
	public DataSource defaultDataSource(){
		DataSource build = DataSourceBuilder.create().build();
		return build;
	}
	
	/**
	 * 配置动态数据源
	 * @param dataSource
	 * @return
	 */
	@Bean("yewuDataSource")
	public DynamicDataSource dynamicDataSource(DataSource dataSource){
		DynamicDataSource dynamicDataSource = new DynamicDataSource(dataSource);
		return dynamicDataSource;
	}
	@Bean
	public SqlSessionFactory yewuSqlSessionFactory(@Qualifier("yewuDataSource") DataSource dataSource) throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		try {
			//添加XML目录
			bean.setMapperLocations(resolver.getResources(yewuMapper));
			return bean.getObject();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	@Bean
	public SqlSessionTemplate yewuSqlSessionTemplate(@Qualifier("yewuSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
		SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory);
		// 使用上面配置的Factory
		return template;
	}
	@Bean(name = "yewuJdbcTemplate")
	public JdbcTemplate yewuJdbcTemplate(@Qualifier("yewuDataSource") DataSource dataSource){
		return new JdbcTemplate(dataSource);
	}
}

/**
 *
 * 相关工具类
 */
@Component
public class DataSourceUtil {

    @Autowired
    private DynamicDataSource dynamicDataSource;

    private final ThreadLocal<String> contextHolder = ThreadLocal.withInitial(() -> "defaultDataSource");

    /**
     * 切换数据源
     * @param key
     */
    public void setDataSourceKey(String key) {
        contextHolder.set(key);
        dynamicDataSource.afterPropertiesSet();
    }

    /**
     * 获取当前数据源
     * @return
     */
    public String getDataSourceKey() {
        return contextHolder.get();
    }

    /**
     * 切换到默认数据源
     */
    public void clearDataSourceKey() {
        contextHolder.remove();
    }

    /**
     * 根据租户ID设置数据源
     * @param tenantId
     * @return
     */
    public void addDataSource(String tenantId, DataSource dataSource) {
        // 没有数据源时添加数据源,有数据源直接使用
        if (!dynamicDataSource.isExistDataSource(tenantId)) {
            // 新增数据源
            dynamicDataSource.addDataSource(tenantId, dataSource);
        }
        // 切换数据源
        setDataSourceKey(tenantId);
        dynamicDataSource.afterPropertiesSet();
    }
}

/**
 * 读取配置文件中数据源相关信息
 * @Date 2020-10-13 15:04
 */

@Data
@Component
@ConfigurationProperties(prefix = "dynamicdatasource")
public class DynamicDataSourceConfig {
	
	private  Map<String, Map<String,Object>> list;
	
	
}

/**
 * 存储动态数据源
 * @Date 2020-10-16 14:13
 */
@Data
public class DynamicDataSourceConfiguration {
	
	private Map<String, DataSource> dynamicDataSource;
}


/**
 * 添加自定义配置 
 * @Date 2020-10-16 14:23
 */
@Configuration
public class MyAppConfig {
	
	Logger log = LoggerFactory.getLogger(MyAppConfig.class);
	
	@Autowired
	private DynamicDataSourceConfig dynamicDataSourceConfig;
	
	/**
	 * 多数据源添加
	 */
	@Bean
	public DynamicDataSourceConfiguration addDynamicDataSourceConfiguration(){
		log.info("初始化动态数据源......");
		DynamicDataSourceConfiguration dynamicDataSourceConfiguration = new DynamicDataSourceConfiguration();
		Map<String,DataSource> dataSourceMap = new HashMap<>();
		Map<String, Map<String, Object>> list = dynamicDataSourceConfig.getList();
		if(list!= null && !list.isEmpty()){
			for (Map.Entry<String, Map<String, Object>> sets:
					list.entrySet()) {
				String key = sets.getKey();
				Map<String, Object> value = sets.getValue();
				Map<String,Object> datasource = (Map<String,Object>)value.get("datasource");
				for (Map.Entry<String, Object>  maps:
						datasource.entrySet()) {
					String s = maps.getValue().toString();
					datasource.put(maps.getKey(),s);
				}
				DataSource dataSource = null;
				try {
					dataSource = DruidDataSourceFactory.createDataSource(datasource);
				} catch (Exception e) {
					e.printStackTrace();
					log.error("初始化动态数据源失败 {}",e.getMessage());
				}
				dataSourceMap.put(key,dataSource);
			}
			dynamicDataSourceConfiguration.setDynamicDataSource(dataSourceMap);
			log.info("初始化动态数据源完成");
		}else{
			log.error("初始化动态数据源失败,未读取到数据源相关配置信息");
		}
		
		return dynamicDataSourceConfiguration;
	}
}

业务需求记录,部分核心代码都是在网上扒下来的,忘记了出处,如有冒犯,请联系我删除;

小白码农,请大神多多指教,共同进步!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值