Fork me on GitHub
时钟canvas

springboot+mybatis的多数据源配置

1.链接数据库yml配置

spring:
  datasource:
    master:
      jdbc-url: jdbc:mysql://localhost:3306/dams?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
      username: root
      password: root    
      driver-class-name: com.mysql.jdbc.Driver

    slave1:
      jdbc-url: jdbc:mysql://localhost:3306/root?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver

    slave2:
      jdbc-url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
      username: root
      password: root
      driver-class-name: com.mysql.jdbc.Driver

  

2.数据源配置

/**
 *  * 关于数据源配置,参考SpringBoot官方文档第79章《Data Access》  * 79. Data Access
 *  * 79.1 Configure a Custom DataSource  * 79.2 Configure Two DataSources  
 */
@Configuration
public class DataSourceConfig {
//将master数据源注入
	@Bean
	@Primary
	@ConfigurationProperties("spring.datasource.master")
	public DataSource masterDataSource() {
		return DataSourceBuilder.create().build();
	}

//将slave1注入
	@Bean
	@ConfigurationProperties("spring.datasource.slave1")
	public DataSource slave1DataSource() {
		return DataSourceBuilder.create().build();
	}

//将slave2注入
	@Bean
	@ConfigurationProperties("spring.datasource.slave2")
	public DataSource slave2DataSource() {
		return DataSourceBuilder.create().build();
	}

// 我们配置了4个数据源,1个master,2两个slave,1个路由数据源。前3个数据源都是为了生成第4个数据源,而且后续我们只用这最后一个路由数据源。
	@Bean
	public DataSource myRoutingDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
			@Qualifier("slave1DataSource") DataSource slave1DataSource,
			@Qualifier("slave2DataSource") DataSource slave2DataSource) {
		Map<Object, Object> targetDataSources = new HashMap<>();
		targetDataSources.put(DBTypeEnum.MASTER, masterDataSource);
		targetDataSources.put(DBTypeEnum.SLAVE1, slave1DataSource);
		targetDataSources.put(DBTypeEnum.SLAVE2, slave2DataSource);
		MyRoutingDataSource myRoutingDataSource = new MyRoutingDataSource();
		myRoutingDataSource.setDefaultTargetDataSource(masterDataSource);// 主库数据源
		myRoutingDataSource.setTargetDataSources(targetDataSources);// 路由数据源
		return myRoutingDataSource;
	}

}

  3.SqlSessionFactory

@EnableTransactionManagement
@Configuration
public class MyBatisConfig {

    @Resource(name = "myRoutingDataSource")
    private DataSource myRoutingDataSource;
//将数据源设置到SqlSessionFactory
    @Bean
    public SqlSessionFactory sqlSessionFactory( MybatisProperties mybatisProperties) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(myRoutingDataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
        sqlSessionFactoryBean.setConfiguration(mybatisProperties.getConfiguration());
        return sqlSessionFactoryBean.getObject();
    }
//将数据源设置到事务平台管理器
    @Bean
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(myRoutingDataSource);
    }
}

  4.

public enum  DBTypeEnum {
    MASTER,SLAVE1,SLAVE2;
}





//定义注解用来强制访问主库
public @interface Master {
}

//数据库切换
public class DBContextHolder {
//定义变量副本
    private static final ThreadLocal<DBTypeEnum> contextHolder = new ThreadLocal<>();
//定义安全自增
    private static final AtomicInteger counter = new AtomicInteger(-1);

    public static void set(DBTypeEnum dbType) {
        contextHolder.set(dbType);
    }

    public static DBTypeEnum get() {
        return contextHolder.get();
    }

    public static void master() {
        set(DBTypeEnum.MASTER);
        System.out.println("切换到master");
    }

    public static void slave() {
        //  轮询切换从数据库
        int index = counter.getAndIncrement() % 2;
        if (counter.get() > 9999) {
            counter.set(-1);
        }
        if (index == 0) {
            set(DBTypeEnum.SLAVE1);
            System.out.println("切换到slave1");
        }else {
            set(DBTypeEnum.SLAVE2);
            System.out.println("切换到slave2");
        }
    }

}

  5.

public class MyRoutingDataSource extends AbstractRoutingDataSource {
    //根据路由来确定map中的sqlsessionFactory
    @Nullable
    @Override
    protected Object determineCurrentLookupKey() {
        return DBContextHolder.get();
    }

}

  6.注入多数据源

public class DataSourceAop {

    @Pointcut("!@annotation(com.tl.base.datasource.annotation.Master) " +
            "&& (execution(* com.tl.base.domain..*.query*(..)) " +
            "|| execution(* com.tl.base.domain..*.get*(..)))")
    public void readPointcut() {

    }

    @Pointcut("@annotation(com.tl.base.datasource.annotation.Master) " +
            "|| execution(* com.tl.base.domain..*.insert*(..)) " +
            "|| execution(* com.tl.base.domain..*.add*(..)) " +
            "|| execution(* com.tl.base.domain..*.update*(..)) " +
            "|| execution(* com.tl.base.domain..*.edit*(..)) " +
            "|| execution(* com.tl.base.domain..*.delete*(..)) " +
            "|| execution(* com.tl.base.domain..*.remove*(..))")
    public void writePointcut() {

    }

    @Before("readPointcut()")
    public void read() {
        DBContextHolder.slave();
    }

    @Before("writePointcut()")
    public void write() {
        DBContextHolder.master();
    }

  

posted @ 2019-12-04 16:25  dragonKings  阅读(393)  评论(0编辑  收藏  举报