zoukankan      html  css  js  c++  java
  • springboot mybatis plus多数据源轻松搞定(下)

    springboot mybatis plus多数据源轻松搞定 (上) 中我们使用了分包的方式实现了一个springboot项目中多个数据源的调用。也对指出了最大的缺点就是不能灵活自由的切换数据源。那么这一篇中,我们探讨一下动态的实现多数据源的方式。可以实现随心所欲的切换数据源。

    基础的配置

    1. 数据源的yml配置和上一结一样,就不在赘述了。
    2. 建立一个枚举类来标识两个数据源
    public enum DataSourceType {
        emanage,ehr
    }
    

    建立一个线程和数据源之间的关联类

    public class DataBaseContextHolder {
        private static final ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<>();
        public static void setDataSourceType(DataSourceType type)
        {
            if(type == null)
            {
                throw new NullPointerException();
            }
    
            contextHolder.set(type);
        }
        public static DataSourceType getDataSourceType()
        {
            DataSourceType type = contextHolder.get();
            if(type == null)
            {
                //确定一个默认数据源
                return DataSourceType.emanage;
            }
            return type;
        }
        
        public static void clearDataSrouceType()
        {
            contextHolder.remove();
        }
    }
    

    代码比较简单。就是当我们设置一个Mapper是通过那个数据源去访问数据的时候,把设置的参数保存在contextHolder中,为了处理线程安全,采用ThreadLocal的方式。

    定义动态数据源

    public class DynamicDataSource extends AbstractRoutingDataSource {
     
        @Override
        protected Object determineCurrentLookupKey() {
     
            return DataBaseContextHolder.getDataSourceType();
        }
    }
    

    定义多数据源

    @Configuration
    @MapperScan("com.emanage.ehr.mapper")
    public class DataSourceConfig {
    
        @Autowired
        private Environment env;
    
        @Bean(name = "datasource1")
        @ConfigurationProperties(prefix = "spring.datasource.emanage")
        public DruidDataSource druidDataSource1()
        {
            return DruidDataSourceBuilder.create().build();
        }
    
        @Bean(name = "datasource2")
        @ConfigurationProperties(prefix = "spring.datasource.ehr")
        public DruidDataSource druidDataSource2()
        {
            return DruidDataSourceBuilder.create().build();
        }
    
        @Bean
        public DynamicDataSource dynamicDataSource(@Qualifier("datasource1") DruidDataSource ds1,
                                                   @Qualifier("datasource2")  DruidDataSource ds2)
        {
            Map<Object, Object> targetDataSource = new HashMap<>();
            targetDataSource.put(DataSourceType.emanage, ds1);
            targetDataSource.put(DataSourceType.ehr, ds2);
            DynamicDataSource dataSource = new DynamicDataSource();
            dataSource.setTargetDataSources(targetDataSource);
            dataSource.setDefaultTargetDataSource(ds1);
            return dataSource;
        }
    
        @Bean
        public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
    
            SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
            // 指定数据源
            bean.setDataSource(dynamicDataSource);
            bean.setMapperLocations(resolver.getResources("classpath*:mapper/**Mapper.xml"));
    
            return bean.getObject();
        }
        @Bean
        public DataSourceTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {
    
            return new DataSourceTransactionManager(dynamicDataSource);
        }
    
    }
    

    使用数据源

    在调用mapper之前,在service中执行以下代码,可以灵活的切换数据源。

    DataBaseContextHolder.setDataSourceType(DataSourceType.emanage); 
    DataBaseContextHolder.setDataSourceType(DataSourceType.ehr); 
    

    优化升级

    感觉在sevrice中调用这些代码太过繁琐,可以自己定义两个注解。

    public @interface DataSourceEmanage{}
    public @interface DataSourceEHr{}
    

    然后建立一个aop类让在有些注解的mapper类执行之前,先执行相应的数据源切换。

    @Aspect
    @Component
    public class DataSourceAop {
        @Before("@annotation(com.example.demo3.config.DataSourceEmanage)")
        public void setEmanageDataSource()
        {
            DataBaseContextHolder.setDataSourceType(DataSourceType.emanage);
        }
    
        @Before("@annotation(com.example.demo3.config.DataSourceEhr)")
        public void setEhrDataSource()
        {
            DataBaseContextHolder.setDataSourceType(DataSourceType.ehr);
        }
    }
    

    只需要在mapper对应的方法上面设置注解,就可以很灵活的实现不同的方法调用不同的数据源。

  • 相关阅读:
    python排序函数sort()与sorted()区别
    python中lambda的用法
    Python中如何获取类属性的列表
    百度编辑器UEditor源码模式下过滤div/style等html标签
    【Flask】关于Flask的request属性
    python json.dumps() json.dump()的区别
    SQLAlchemy技术文档(中文版)(全)
    Flask中'endpoint'(端点)的理解
    SqlAlchemy个人学习笔记完整汇总-转载
    MySQL数据类型和常用字段属性总结
  • 原文地址:https://www.cnblogs.com/bbird/p/13164553.html
Copyright © 2011-2022 走看看