Skip to content

Latest commit

 

History

History
172 lines (133 loc) · 4.79 KB

File metadata and controls

172 lines (133 loc) · 4.79 KB

动态数据源

简要说明

用于动态数据源,多数据源处理。 使用方法参数动态切换数据源,支持动态添加数据源。

安装

<dependency>
    <groupId>com.github.yhqy</groupId>
    <artifactId>multi-datasource-spring-boot-starter</artifactId>
    <version>1.1.0</version>
</dependency>

如何使用?(以mybatis为例)

表结构

假设我们有三个库,db_common, db_1 , db_2.

  • db_common作为默认数据源。有表 datasource:
id url drive username password
1 jdbc:mysql://localhost:3306/db_1 com.mysql.jdbc.Driver root password
2 jdbc:mysql://localhost:3306/db_2 com.mysql.jdbc.Driver root password
  • db_1有表: user
id username
1 db1_user
  • db_2有表: user
id username
1 db2_user

实体类

@Data
public class DataSourceDO {
    private int id;
    private String url;
    private String drive;
    private String username;
    private String password;
}

@Data
public class User {
    private int id;
    private String username;
}

DAO

@Mapper
public interface TestMapper extends DAO {

    @Select(" select * from datasource where id = #{id} ")
    DataSourceDO queryDataSourceById(@Param("id") Integer id);

    @Select(" select * from user limit 1")
    User queryUser(@Did Integer datasourceId);

}

注意:此处必须实现DAO接口,DAO接口只是一个标识类,不包含任何方法

数据源配置

@Component
public class DemoDataSourceFactory implements DataSourceFactory {

    @Autowired
    private TestMapper testMapper;

    @Override
    public DataSource createDefaultDataSource() {
        return DataSourceBuilder.create().username("root").password("password")
                .url("jdbc:mysql://localhost:3306/db_common")
                .build();
    }

    @Override
    public DataSource createDataSource(String key) {
        DataSourceDO dataSourceDO = testMapper.queryDataSourceById(Integer.parseInt(key));
        return DataSourceBuilder.create().username(dataSourceDO.getUsername()).password(dataSourceDO.getPassword()).url(dataSourceDO.getUrl()).build();
    }

    @Override
    public String key() {
        return "id";
    }
}

测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

    @Autowired
    private TestMapper testMapper;

    @Test
    public void contextLoads() {
        User user1 = testMapper.queryUser(1);
        Assert.assertEquals("db1_user", user1.getUsername());
        User user2 = testMapper.queryUser(2);
        Assert.assertEquals("db2_user", user2.getUsername());
    }

}

以上test类中,当testMapper.queryUser(1)时,发现当前系统没有key=1所对应的数据源,于是会调用我们配置的DataSourceFactory.createDataSource(key)方法创建, 此时会通过testMapper.queryDataSourceById(key)到datasource表中查询数据源配置信息(因为queryDataSourceById()方法参数中没有使用@Did注解,所以会使用默认数据源), 获得数据源配置信息后,构建datasource并返回。系统会缓存此datasource,后续使用到此datasource时无需再次创建。

@Did 支持的注解参数类型

/**
* 实现DAO接口(DAO接口是一个标志接口,无任何需要实现的方法)
*/
@Mapper
public interface TestMapper extends DAO {

    //1
    @Select(" select * from datasource where id = #{id} ")
    DataSourceDO getById(@Param("id") Integer id);

    //2
    @Select(" select * from user limit 1")
    User queryUser(@Did Integer datasourceId);

    //3
    @Select(" select * from user limit 1")
    User queryUser(@Did User user);

    //4
    @Select(" select * from user limit 1")
    User queryUser(@Did Map map);

    //5
    @Select(" select * from user limit 1")
    User queryUser(@Did List<User> user);
    
    //6
    @Select(" select * from user limit 1")
    User queryUser(@Did List<Map> map);

}

说明:

  • 1: 未使用@Did标记,使用默认数据源;
  • 2:使用@Did标记,使用datasourceId.toString()后对应的数据源,此处支持基本数据类型及string类型;
  • 3:使用@Did标记,使用user.getDataSourceId()方法获得的值所对应的数据源(bean类型,通过DataSourceFactory.key()方法获得key所对应的get方法);
  • 4:使用@Did标记,使用map.get("dataSourceId")获得的值对应的数据源;
  • 5:使用@Did标记,使用List.get(0)后获得的第一个User,然后使用通过user.getDataSourceId()获得的key对应的数据源;
  • 6:使用@Did标记,使用List.get(0)后获得的第一个map,然后使用map.get("dataSourceId")获得的值对应的数据源;