springboot-mybatis多数据源实战的两个例子

一、mybatis-plus的动态数据源

1、关键pom


        
            mysql
            mysql-connector-java
            8.0.15
        

        
        
            com.baomidou
            dynamic-datasource-spring-boot-starter
            3.1.0
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.1.0
        

2、application.properties动态数据源配置:

spring.datasource.dynamic.datasource.master.url加黑的是mybatis-plus固定死的,不能修改,没有加黑的是动态数据源的名称,可以自定义
##数据源
#主
spring.datasource.dynamic.primary=master
spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.master.url=jdbc:mysql://192.168.43.10:3306/oauth?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.dynamic.datasource.master.username=root
spring.datasource.dynamic.datasource.master.password=123456
#备
spring.datasource.dynamic.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.slave.url=jdbc:mysql://192.168.43.10:3306/oauth-resource?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.dynamic.datasource.slave.username=root
spring.datasource.dynamic.datasource.slave.password=123456
##mybatis plus
mybatis-plus.mapper-locations=classpath*:/mapper/*.xml

3、dao层注解

@DS("slave")
@Mapper
public interface TbContentMapper extends BaseMapper {
    List getAll();
}



@DS("master")
@Mapper
public interface TbUserMapper extends BaseMapper {
    TbUser getByUsername(@Param("userName") String userName);
}

4、启动类

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class Oauth2ServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(Oauth2ServerApplication.class, args);
    }
}

 

二、mybatis+aop自定义动态数据源

1、关键pom


        
            mysql
            mysql-connector-java
            8.0.15
        

        
            com.baomidou
            mybatis-plus-boot-starter
            3.1.0
        

2、application.properties动态数据源配置

#数据源
#主
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.jdbc-url=jdbc:mysql://192.168.43.10:3306/oauth?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.master.username=root
spring.datasource.master.password=123456

#备
spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.jdbc-url=jdbc:mysql://192.168.43.10:3306/oauth-resource?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.slave.username=root
spring.datasource.slave.password=123456

3、定义一个动态数据源:继承AbstractRoutingDataSource 抽象类,并重写determineCurrentLookupKey()方法

package com.allen.test.mybatis;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        DataSourceType.DataBaseType dataBaseType = DataSourceType.getDataBaseType();
        return dataBaseType;
    }

}

4、创建一个切换数据源类型的类: ThreadLocal就是为了线程的安全性,每个线程之间不会相互影响

package com.allen.test.mybatis;

public class DataSourceType {

    public enum DataBaseType {
        MASTER, SLAVE
    }

    // 使用ThreadLocal保证线程安全
    private static final ThreadLocal TYPE = new ThreadLocal();

    // 往当前线程里设置数据源类型
    public static void setDataBaseType(DataBaseType dataBaseType) {
        if (dataBaseType == null) {
            throw new NullPointerException();
        }
        System.err.println("[将当前数据源改为]:" + dataBaseType);
        TYPE.set(dataBaseType);
    }

    // 获取数据源类型
    public static DataBaseType getDataBaseType() {
        DataBaseType dataBaseType = TYPE.get() == null ? DataBaseType.MASTER : TYPE.get();
        System.err.println("[获取当前数据源的类型为]:" + dataBaseType);
        return dataBaseType;
    }

    // 清空数据类型
    public static void clearDataBaseType() {
        TYPE.remove();
    }

}

5、定义多个数据源:主要是将定义好的多个数据源放在动态数据源中

package com.allen.test.mybatis;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 参考博客地址:https://blog.csdn.net/tuesdayma/article/details/81081666?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
 */
@Configuration
@MapperScan(basePackages = "com.allen.test.dao", sqlSessionFactoryRef = "SqlSessionFactory")
public class DataSourceConfig {
    @Primary
    @Bean(name = "masterDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource getDateSource1() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource getDateSource2() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "dynamicDataSource")
    public DynamicDataSource DataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
            @Qualifier("slaveDataSource") DataSource slaveDataSource) {
        Map targetDataSource = new HashMap<>();
        targetDataSource.put(DataSourceType.DataBaseType.MASTER, masterDataSource);
        targetDataSource.put(DataSourceType.DataBaseType.SLAVE, slaveDataSource);
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSource);
        dataSource.setDefaultTargetDataSource(masterDataSource);
        return dataSource;
    }
    @Bean(name = "SqlSessionFactory")
    public SqlSessionFactory dynamicSqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dynamicDataSource);
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
        return bean.getObject();
    }
}

6、定义AOP:就是不同业务切换不同数据库的入口,后续会修改为注解

package com.allen.test.mybatis;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class DataSourceAop {
    @Before("execution(* com.allen.test.dao..*.getByUsername*(..))")
    public void setDataSource2master() {
        System.err.println("master业务");
        DataSourceType.setDataBaseType(DataSourceType.DataBaseType.MASTER);
    }

    @Before("execution(* com.allen.test.dao..*.getAll*(..))")
    public void setDataSource2slave() {
        System.err.println("slave业务");
        DataSourceType.setDataBaseType(DataSourceType.DataBaseType.SLAVE);
    }
}

7、验证测试:定义两个mapper,分别对应不同的切点

package com.allen.test;


import com.allen.test.dao.TbContentMapper;
import com.allen.test.dao.TbUserMapper;
import com.allen.test.model.TbContent;
import com.allen.test.model.TbUser;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestServerApplication.class)
public class MutilDataSourceTest {

    @Autowired(required = false)
    private TbContentMapper tbContentMapper;
    @Autowired(required = false)
    private TbUserMapper tbUserMapper;
    
    @Test
    public void test() throws Exception {
        //aop会切到master数据源
        TbUser tbUser = tbUserMapper.getByUsername("admin");
        System.out.println(tbUser);
        //aop会切到slave数据源
        List all = tbContentMapper.getAll();
        System.out.println(all);
    }
}

 

 

 

 

你可能感兴趣的:(mybatis)