zoukankan      html  css  js  c++  java
  • SpringCloud多数据源实现

    1、枚举多数据源-定义一一对应变量

    /**
    *
    * 列出所有的数据源key(常用数据库名称来命名)
    * 注意:
    * 1)这里数据源与数据库是一对一的
    * 2)DatabaseType中的变量名称就是数据库的名称
    */

    public enum DatabaseType {
      test1,test2
    }

    2、将数据源变量保存在线程变量中

    /**
    *  
    * 作用:1、保存一个线程安全的DatabaseType容器
    */
    public class DatabaseContextHolder {

    //将数据源枚举变量保存在线程变量中
    private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<DatabaseType>();

    public static void setDatabaseType(DatabaseType type) {
    contextHolder.set(type);
    }

    public static DatabaseType getDatabaseType() {
    return contextHolder.get();
    }
    }

    3、动态数据源

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

    /**
    *  动态数据源(需要继承AbstractRoutingDataSource)
    */
    public class DynamicDataSource extends AbstractRoutingDataSource {
    protected Object determineCurrentLookupKey() {
    return DatabaseContextHolder.getDatabaseType();
    }
    }

    4、数据源配置

    数据源1:

    test1.driverClassName=org.postgresql.Driver
    test1.url=jdbc:postgresql://localhost:5432/test1
    test.username=test1

    test1.password=123456

    test1.remove-abandoned=true
    test1.remove-abandoned-timeout=120
    test1.test-on-borrow=true

    数据源2:

    test2.driverClassName=org.postgresql.Driver
    test2.url=jdbc:postgresql://localhost:5432/test2
    test2.username=test2

    test2.password=123456

    test2.remove-abandoned=true
    test2.remove-abandoned-timeout=120
    test2.test-on-borrow=true

    5、数据源初始化

    /**
    * springboot集成mybatis的基本入口
    * 1)创建数据源(如果采用的是默认的tomcat-jdbc数据源,则不需要)
    * 2)创建SqlSessionFactory
    * 3)配置事务管理器,除非需要使用事务,否则不用配置
    *
    */
    @Configuration // 该注解类似于spring配置文件
    @MapperScan(basePackages = "cn.test.mapper")
    public class MyBatisConfig {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private Environment env;

    @Bean
    public DataSource test1DataSource() throws Exception {
    Properties props = new Properties();
    props.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, env.getProperty("test1.driverClassName"));
    props.put(DruidDataSourceFactory.PROP_URL, env.getProperty("test1.url"));
    props.put(DruidDataSourceFactory.PROP_USERNAME, env.getProperty("test1.username"));

    // 获取数据库密码
    props.put(DruidDataSourceFactory.PROP_PASSWORD, env.getProperty("test1.password"));
    props.put(DruidDataSourceFactory.PROP_REMOVEABANDONED, env.getProperty("test1.remove-abandoned"));
    props.put(DruidDataSourceFactory.PROP_REMOVEABANDONEDTIMEOUT, env.getProperty("test1.remove-abandoned-timeout"));
    props.put(DruidDataSourceFactory.PROP_TESTONBORROW, env.getProperty("test1.test-on-borrow"));
    return DruidDataSourceFactory.createDataSource(props);
    }

    @Bean
    public DataSource test2DataSource() throws Exception {
    Properties props = new Properties();
    props.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, env.getProperty("test2.driverClassName"));
    props.put(DruidDataSourceFactory.PROP_URL, env.getProperty("test2.url"));
    props.put(DruidDataSourceFactory.PROP_USERNAME, env.getProperty("test2.username"));

    // 获取数据库密码 
    props.put(DruidDataSourceFactory.PROP_PASSWORD, env.getProperty("test2.password"));
    props.put(DruidDataSourceFactory.PROP_REMOVEABANDONED, env.getProperty("test2.remove-abandoned"));
    props.put(DruidDataSourceFactory.PROP_REMOVEABANDONEDTIMEOUT, env.getProperty("test2.remove-abandoned-timeout"));
    props.put(DruidDataSourceFactory.PROP_TESTONBORROW, env.getProperty("test2.test-on-borrow"));
    return DruidDataSourceFactory.createDataSource(props);
    }

    /**
    * @throws Exception
    * @Primary 该注解表示在同一个接口有多个实现类可以注入的时候,默认选择哪一个,而不是让@autowire注解报错
    * @Qualifier 根据名称进行注入,通常是在具有相同的多个类型的实例的一个注入(例如有多个DataSource类型的实例)
    */
    @Bean
    @Primary
    public DynamicDataSource dataSource() throws Exception {
    DataSource dataSource1 = test1DataSource();

    DataSource dataSource2 = test2DataSource();
    Map<Object, Object> targetDataSources = new HashMap<>();
    targetDataSources.put(DatabaseType.test1, dataSource1);

    targetDataSources.put(DatabaseType.test2, dataSource2);

    DynamicDataSource dataSource = new DynamicDataSource();
    dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
    dataSource.setDefaultTargetDataSource(dataSource1 );// 默认的datasource设置为dataSource 1
    return dataSource;
    }

    /**
    * 根据数据源创建SqlSessionFactory
    */
    @Bean
    public SqlSessionFactory sqlSessionFactory(DynamicDataSource ds) throws Exception {
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(ds);// 指定数据源(这个必须有,否则报错)
    // 加载配置mybatis-config
    DefaultResourceLoader configResourceLoader = new DefaultResourceLoader();
    Resource configResource = configResourceLoader.getResource("mybatis-config.xml");
    bean.setConfigLocation(configResource);
    // 添加mapper文件XML目录
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = resolver.getResources("classpath:cn/test/mapper/*.xml");
    bean.setMapperLocations(resources);

    return bean.getObject();
    }

    /**
    * 配置事务管理器
    */
    @Bean
    public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
    return new DataSourceTransactionManager(dataSource);
    }

    }

    6、

    ①查询test1的数据时,可以直接调用对应的mapper;(因为test1是默认数据源)

    ②查询test2的数据时,需要在调用之前指定数据源,如下代码:

    DatabaseContextHolder.setDatabaseType(DatabaseType.test2);

    ③同时需要查询test1和test2的数据时,需要在调用之前指定正确的数据源。

  • 相关阅读:
    三角形外接圆与内切圆
    不等式证明
    不等式证明
    被 6 整除
    被 6 整除
    从切比雪夫不等式到大数定理
    JAVA轻量级文件监控
    Windows应用程序的消息处理机制
    JUnit中@Test的运行顺序
    MyReport报表引擎2.2.0.0新功能
  • 原文地址:https://www.cnblogs.com/wangymd/p/11011516.html
Copyright © 2011-2022 走看看