提示:SpringBoot工程这里可以在properties文件里直接进行配置
#数据源配置一(默认数据源)
spring.datasource.test1.jdbc-url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.test1.username=root
spring.datasource.test1.password=123456
spring.datasource.test1.driver-class-name=com.mysql.jdbc.Driver
#数据源配置二
spring.datasource.test2.jdbc-url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.test2.username=root
spring.datasource.test2.password=123456
spring.datasource.test2.driver-class-name=com.mysql.jdbc.Driver
我们用枚举类来定义数据源
代码如下(示例):
public enum DBEnum {
test1("test1Datasource"),
test2("test2Datasource");
private String value;
DBEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
/**
* 提供动态数据源的类
*/
public class DynamicDataSource extends AbstractRoutingDataSource{
/**
* 覆盖AbstractRoutingDataSource查找当前数据源id的方法。
**/
@Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}
/**
* 数据源的id绑定当前线程
*/
public class DbContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 设置数据源(数据源字符串名称)
*/
public static void setDbType(DBEnum dbEnum) {
contextHolder.set(dbEnum.getValue());
}
/**
* 取得当前数据源(数据源字符串名称)
*/
public static String getDbType() {
return contextHolder.get();
}
/**
* 清除上下文数据源
*/
public static void clearDbType() {
contextHolder.remove();
}
}
@Configuration
public class DbConfig {
@Bean(name = "test1Datasource")
@ConfigurationProperties(prefix = "spring.datasource.test1") //可以将配置文件的属性除去前缀后,赋值到bean中
public DataSource test1Datasource(){
DataSource dataSource = DataSourceBuilder.create().build();
return dataSource;
}
@Bean(name = "test2Datasource")
@ConfigurationProperties(prefix = "spring.datasource.test2")
public DataSource test2Datasource(){
DataSource dataSource = DataSourceBuilder.create().build();
return dataSource;
}
/**
* 动态数据源
* @return
*/
@Bean(name = "dynamicDataSource")
@Primary /**设置成Primary时,注入时如果是按类型注入的话,会优先!而实际上[自动的配置]里面就是按DataSource类型注入的*/
public DataSource dataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 配置多数据源 <==>
Map<Object, Object> dsMap = new HashMap<>(2);
dsMap.put("test1Datasource", test1Datasource());
dsMap.put("test2Datasource", test2Datasource());
dynamicDataSource.setTargetDataSources(dsMap);
// 默认数据源 <==>
dynamicDataSource.setDefaultTargetDataSource(test1Datasource());
return dynamicDataSource;
}
}
/*
*
原来用xml配置动态数据源的形式
*/
@Mapper
public interface UserMapper {
@Insert("insert into user (id,name) values (#{id},#{name}) ")
public void insert(@Param("id")Integer id ,@Param("name")String name);
@Select("select * from user")
@ResultType(User.class)
public List<User> selectList();
@Update("update user set name = #{name} where id = #{id}")
public void updateByKey(User user);
@Delete("delete from user where id = #{id}")
public void deleteById(Integer id);
}
提示:这里使用ThreadLocal记得要释放内存,尤其是利用线程池的时候,不然容易诱发内存泄露
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes= Application.class)
public class TestMapper {
@Autowired
private UserMapper userMapper;
@Test
public void test1(){
userMapper.insert(1, "张三");
DbContextHolder.setDbType(DBEnum.test2);
userMapper.insert(1, "张三");
DbContextHolder.clearDbType();
}
}
按照以上的步骤测试会出现一下循环依赖报错的问题:
出现问题的原因是跟数据源自动配置冲突了,我们可以排除掉数据源自动配置的类就好了