mybatis多数据库配置与详解

mybatis多数据源配置与详解

记录下mybatis多数据源的使用过程,并对代码作用进行简述(只是个人对代码功能的猜测,如有错误请在评论区指出)。

目录

mybatis多数据源配置与详解

1,下载案例

2,案例过程讲解

2.1 DatabaseContextHolder类

2.2 DataSourceAop类

2.3 DynamicDataSource类

2.4 MyDatabase类

2.5MultDataSource类


1,下载案例

https://gitee.com/leonzhang2013/mybaits__multiple_data_sources 

ps:找了很多资料,这个案例是其中很详细的。备用地址:https://download.csdn.net/download/qq_42892858/13099539

2,案例过程讲解

除了选框选中的部分,其他和普通项目一样。

2.1 DatabaseContextHolder类

这个类就像一个箱子,A把要使用数据源的名字放进去,B操作数据的时候读箱子里的内容就知道要操作那个数据库。

public class DatabaseContextHolder {

    private static final ThreadLocal<String> contextHolder = new ThreadLocal(); //这就是箱子

    public static void setDataSourceType(String dataSourceType) {

        System.out.println("正在设置 数据 源:"+dataSourceType);
        contextHolder.set(dataSourceType);
    }

    public static String getDataSourceType() {
        System.out.println("获取当前的数据源:"+contextHolder.get());
        return contextHolder.get();
    }

}

2.2 DataSourceAop类

上边说A操作箱子,DataSourceAop在这就相当于一个操作箱子的角色(当然可以通过其实方式操作箱子)

为什么用Aop,因为Aop是每次操作都会执行的,就可以通过辨别操作者来更改箱子中的内容

@Aspect
@Component
public class DataSourceAop {

    //MultDataSource是多数据源,所有的数据源都存放在这里面
    @Autowired
    MultDataSource multDataSource;


    @Before("execution(* com.example.mybatis.mapper..*.get*(..)) || " +
            "execution(* com.example.mybatis.mapper..*.list*(..)) ||"+
            "execution(* com.example.mybatis.mapper..*.select*(..))")
    public  void setReadDataSource(){
        DatabaseContextHolder.setDataSourceType(getReadKey());
        System.out.println("我是读");
    }

    @Before("execution(* com.example.mybatis.mapper..*.add*(..)) || " +
            "execution(* com.example.mybatis.mapper..*.update*(..)) ||"+
            "execution(* com.example.mybatis.mapper..*.insert*(..)) ||"+
            "execution(* com.example.mybatis.mapper..*.delete*(..))")
    public  void setWriteDataSource(){
        DatabaseContextHolder.setDataSourceType(getMainKey());
        System.out.println("我是写");
    }

    /**
     * 轮询方式
     * 这里没什么难的,就是选择往箱子中放什么内容。与主题无关
     */
    int m = 0;
    public String getMainKey(){
        List<String> readKeys = multDataSource.getMainKeys();
        m ++;
        m = m%readKeys.size();
        return readKeys.get( m );
    }

    int i = 0;
    public String getReadKey(){
        List<String> readKeys = multDataSource.getReadKeys();
        i ++;
        i = i%readKeys.size();
       return readKeys.get( i );
    }

}

2.3 DynamicDataSource类

此类继承了AbstractRoutingDataSource类,并重写了determineCurrentLookupKey方法。在这个方法中返回了要操作数据源的名字,这个名字就是在箱子(DatabaseContextHolder)中获取的,可见这个类就相当于角色B。但是要注意mybatis现在是不知道这个类存在的。

public class DynamicDataSource extends AbstractRoutingDataSource{

    @Override
    protected Object determineCurrentLookupKey() {
        String dataSourceType = DatabaseContextHolder.getDataSourceType();
        System.out.println("动态获取到的 数据源key == "+dataSourceType);
        return dataSourceType;
    }
}

2.4 MyDatabase类

这个类就是存放数据源的配置,没要点

@Data
public class MyDatabase {

    private String password;
    private String driver;
    private String username;
    private String url;
    private String type;
}

2.5MultDataSource类

这个类是核心类,也是直接和mybatis打交道的类。


/**
 * @Author: zll
 * @Date @{DATE} 21:26
 */
//配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法
@Configuration
//在编译之后会生成相应的接口实现类
@MapperScan(basePackages = "com.example.mybatis.mapper")
//加载指定配置文件 multidatabase.properties
@PropertySource(value = "classpath:multidatabase.properties", encoding = "utf-8")
//从配置文件中提取my开头的句子
@ConfigurationProperties("my")
@Data
public class MultDataSource {

    public static final String MAIN = "main";
    public static final String READ = "read";

    public List<String> mainKeys = new ArrayList<>();
    public List<String> readKeys = new ArrayList<>();

    @Value("${my.datasource.driver}")
    private String driver;

    /**
     *  读取配置文件。由以下两个注解实现
     *  也可以说运行时,n个数据源信息(由multidatabase.properties提供)会由spring自动放在里面
     *  @PropertySource(value = "classpath:multidatabase.properties", encoding = "utf-8")
     *  @ConfigurationProperties("my")
     */
    private List<MyDatabase> datasource;

    //这个方法返回druid数据源,创建数据源信息由datasource提供 
    public DruidDataSource getDataSource(MyDatabase database) {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setUrl(database.getUrl());
        druidDataSource.setUsername(database.getUsername());
        druidDataSource.setDriverClassName(driver);
        druidDataSource.setPassword(database.getPassword());
        druidDataSource.setInitialSize(1);
        druidDataSource.setMaxWait(6000);
        druidDataSource.setMinIdle(8);
        return druidDataSource;
    }

    //这个方法管理所有的数据源, setTargetDataSources设置当前的数据库
    @Bean
    //用@Primary 告诉spring 在犹豫的时候优先选择哪一个具体的实现。
    @Primary
    public DynamicDataSource dataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        //对targetDataSources初始化,完成后targetDataSources存放所有数据源信息
        for (int i = 0; i < datasource.size(); i++) {
            String type = datasource.get(i).getType();
            DruidDataSource dataSource = getDataSource(datasource.get(i));
            if (MAIN.equals(type)) {
                mainKeys.add(MAIN+i);
                targetDataSources.put(MAIN+i,dataSource);
            } else {
                readKeys.add(READ+i);
                targetDataSources.put(READ+i,dataSource);
            }
        }
        
        DynamicDataSource dataSource = new DynamicDataSource();
        // 将所有的数据源提交给dataSource返回给mybatis
        dataSource.setTargetDataSources(targetDataSources);
        // 告诉mybatis默认使用的数据源,在这个项目中这个数据源不会使用,因为aop的原因每次执行前都会指定一个数据源
        dataSource.setDefaultTargetDataSource(targetDataSources.get(mainKeys.get(0)));
        return dataSource;
    }

    //DynamicDataSource虽然知道要调用的数据源,但mybatis不知道,这里就相当于把DynamicDataSource告诉mybatis.这样mybatis每次操作数据库时
    //都要先从DynaicDataSource中获取要操作数据库的名字,然后在去操作数据库
    @Bean
    public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }

}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值