前言:
demo的包结构
一、项目配置相关。
1.1 pom.xml 省略, spring-boot 版本1.4.3
1.2 application-dev.properties
#数据源配置一(兼默认数据源)
spring.datasource.test1.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.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
二、动态数据源相关类.
2.1 DBEnum : (用来包装字符串的用处!)
public enum DBEnum {
test1("test1Datasource"),
test2("test2Datasource");
private String value;
DBEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
2.2:DynamicDataSource (提供数据源的类,覆盖方法是返回在自身数据源map中查询的字符串-->由线程绑定变量提供)
/**
* 提供动态数据源的类
*/
public class DynamicDataSource extends AbstractRoutingDataSource{
/**
* 覆盖AbstractRoutingDataSource查找当前数据源id的方法。
**/
@Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}
2.3 DbContextHolder (用ThreadLocal变量存储查询数据源的字符串)
/**
* 数据源的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();
}
}
2.4 DbConfig (将普通的数据源配置到我们的动态数据源,将此动态数据源整合到上层其他配置中,比如注入到sqlsessionFactory,transcationManager等,但是实际上我这里只加了一个@Primary就可以利用默认的配置了。)
@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();
// 配置多数据源 <==> <property name="targetDataSources">
Map<Object, Object> dsMap = new HashMap<>(2);
dsMap.put("test1Datasource", test1Datasource());
dsMap.put("test2Datasource", test2Datasource());
dynamicDataSource.setTargetDataSources(dsMap);
// 默认数据源 <==> <property name="defaultTargetDataSource" ref="test1" />
dynamicDataSource.setDefaultTargetDataSource(test1Datasource());
return dynamicDataSource;
}
}
/*
*
原来用xml配置动态数据源的形式
<bean id="dataSource" class="com.jbzy1dt.common.datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="test1" value-ref="test1" />
<entry key="test2" value-ref="test2" />
</map>
</property>
<property name="defaultTargetDataSource" ref="test1" />
</bean>*/
三、Mapper类及测试。
3.1 UserMapper
@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);
}
3.2 TestMapper
@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, "张三");
}
}