Mybatis实现动态数据源

动态数据源

需求:就是不同模块要存在不同的数据库中,就要实现动态数据源
基本思路:

1.创建一个动态的数据源DynamicDataSource,同事创建一个配置类DynamicDataSourceConfig配置类,这个配置类在Spring初始化的时候就在动态数据源中配置两种数据源

2.创建自定义注解@DataSource 标注在dao接口方法上,表明用哪个数据源

3.aop切入我们dao方法是,接口自定义注解给DynamicDataSource设置用哪个数据源

​ 这样不同的dao层的方法通过@DataSource就可以自定义我们需要用的数据源

代码

自定义注解:

/**
 * 备注:自定义数据源选择注解
 **/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String name() default "";
}

配置类:

@Configuration
@Component
public class DynamicDataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.druid.xiaobin-master")
    public DataSource xiaobinMasterDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.druid.xiaobin-slave")
    public DataSource  xiaobinSlaveDataSource(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource xiaobinMasterDataSource, DataSource xiaobinSlaveDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("xiaobin-master",xiaobinMasterDataSource);
        targetDataSources.put("xiaobin-slave", xiaobinSlaveDataSource);
        return new DynamicDataSource(xiaobinMasterDataSource, targetDataSources);
    }
}

切面:

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("@annotation(com.dynamicdatasource.demo.Config.DataSource)")
    public void dataSourcePointCut() {

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();

        DataSource dataSource = method.getAnnotation(DataSource.class);
        if(dataSource == null){
            DynamicDataSource.setDataSource("xiaobin-master");
        }else {
            DynamicDataSource.setDataSource(dataSource.name());
        }

        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }
}

dao层接口:

@Mapper
public interface UserMapper {
    @DataSource(name = "xiaobin-master")
    public Map queryAllWithMaster();

    @DataSource(name = "xiaobin-master")
    Map queryAllWithSlave();
}

配置文件中配置两个数据源:

spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          xiaobin-master: # 主数据源
            driverClassName: com.mysql.jdbc.Driver
            username: root
            password: root
            url: jdbc:mysql://localhost:3306/mydb1?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
          xiaobin-slave: # 从数据源
            driverClassName: com.mysql.jdbc.Driver
            username: root
            password: root
            url: jdbc:mysql://localhost:3306/mydb2?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8
mybatis:
 mapper-locations: classpath:mapper/*.xml

controller:

@RestController
@RequestMapping
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @GetMapping("/{name}/list")
    public Map list(@PathVariable("name")String name){
        if(name.equals("master")){
            return userMapper.queryAllWithMaster();
        }else{
            return userMapper.queryAllWithSlave();
        }
    }
}

另外主启动类中要导入我们自定义的配置类

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class}) // 把默认的配置类排除掉
@MapperScan(basePackages = "com.dynamicdatasource.demo.Dao")
@Import({DynamicDataSourceConfig.class}) //导入
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

mapper文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dynamicdatasource.demo.Dao.UserMapper">
    <select id="queryAllWithMaster" resultType="java.util.Map">
        select * from mydb1.user t where t.NAME = 'zs'
    </select>
    <select id="queryAllWithSlave"  resultType="java.util.Map">
         select * from mydb2.course t where t.c = '1'
    </select>
</mapper>
  • 更新:对于数据源用TheadLocal 保证每个线程的数据源不一样的,spring中对象是单例的,不用TheadLocal会把其他的线程的数据源修改了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值