• 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();
        }
    

      

    如果你不知道自己要去哪里,那么去哪里都是一样
  • 相关阅读:
    DotNetty是微软的Azure团队,使用C#实现的Netty的版本发布
    C# 与 .NET Framework 对应关系
    C# 基于Directshow.Net lib库 USB摄像头使用DirectShow.NET获取摄像头视频流
    Actor模型的状态(State)+行为(Behavior)+邮箱(Mailbox)
    c# 无法加载DLL:找不到指定的模块(异常来自HRESULT:0X8007007E)
    管道式编程(Pipeline Style programming)
    Word文档转Markdown插件(Windows)
    纯Java实现定时任务(转)
    Spring MVC使用Schedule实现定时任务
    Spring Boot使用Schedule实现定时任务
  • 原文地址:https://www.cnblogs.com/dragonKings/p/11983676.html
Copyright © 2020-2023  润新知