手动创建jdbcTemplate多数据源

  • 业务场景:

老工程再次添加新需求,需要读取另外的一个数据库。

详细说明:有些工程已经稳定运行很久,突然接到新需求,需要升级。例如,从外部A数据库中获取数据。处理后,再保存到本地B数据库中。

这种老工程再次开发的场景,一般来说是小修、小补、小升级。但对于老工程,因为开发时间比较久,但工程已经经过多次维护和时间的检验,已经进入稳定运行状态。

对于这样的场景,如果工程中的数据源(DataSource)是全局性的,千万要注意,可别小升级带来大麻烦。

如果场景相似,小蒋个人的建议是:尽量“多新增,少修改。能不改,就别改”。

  • 解决方案:

“手动新建数据源,尽量别影响原始的数据源”。

在Spring Boot中,jdbcTemplate、MyBatis、JPA这三种实现都可以配置多数据源。

其中,MyBatis和JPA是两种主流的实现方式。所以,小蒋今天就准备和大家一起通过“手动”新建jdbcTemplate这种实现方式,一起体验一下“多新增,少修改。能不改,就别改” 这个策略。

  • 方案说明:

有些老工程已经开发很久了,当时的工程设计资料可能已经不全了。咱先不聊开发人员是否都在职,就算全部都在职。但是,别小瞧“时间的威力”,研发人员能剩下的记忆也非常有限。这个时候,去修改一个全局的DataSource,其风险是非常大的。所以,如果是“小修、小补、小升级”,这个时候“多新增,少修改。能不改,就别改”这个策略可能更合适。

示例:

        1.选择Spring Boot版本:

(咱们的“业务场景”是一个老工程,小蒋选择Spring Boot 1.5.6.RELEASE 这个版本)


<parent>  
        <groupId>org.springframework.boot</groupId>  
	    <artifactId>spring-boot-starter-parent</artifactId>  
	    <version>1.5.6.RELEASE</version>  
	    <relativePath/> <!-- lookup parent from repository -->  
</parent>


        2.添加Maven的依赖:

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
</dependency>  
  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-tomcat</artifactId>  
    <scope>provided</scope>  
</dependency>  
  
<!--druid依赖-->  
<dependency>  
    <groupId>com.alibaba</groupId>  
    <artifactId>druid-spring-boot-starter</artifactId>  
    <version>1.1.10</version>  
</dependency>  
  
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->  
<dependency>  
    <groupId>mysql</groupId>  
    <artifactId>mysql-connector-java</artifactId>  
    <version>5.1.49</version>  
    <scope>runtime</scope>  
</dependency>  
  
<dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-jdbc</artifactId>  
    <version>4.3.8.RELEASE</version>  
</dependency>

注意:数据库连接池Druid依赖,小蒋选择了druid-spring-boot-starter。优势在于,它是用于帮助使用者在Spring Boot项目中轻松集成Druid数据库连接池和监控的。(druid-spring-boot-starter项目地址

        3.配置数据源:

在application.properties文件中配置“两个”,“新”的数据源。

注意,这里配置的新数据源”和老项目里原来“jpa的数据源”,配置的key是不同的。

spring.datasource.one.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8  
spring.datasource.one.username=root  
spring.datasource.one.password=12345678  
spring.datasource.one.type=com.alibaba.druid.pool.DruidDataSource  
  
spring.datasource.two.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8  
spring.datasource.two.username=root  
spring.datasource.two.password=12345678  
spring.datasource.two.type=com.alibaba.druid.pool.DruidDataSource

        4.新增DataSourceConfig类:

在application.properties配置文件中,我们对数据源做了区分“one”和“tow”。KEY的设置不符合spring boot自动加载的规则,所以需要DataSourceConfig类,我们手动加载。

@Configuration  
public class DataSourceConfig {  
  
    @Bean  
    //@Primary  这个注解是设置默认数据源,老项目中原来的数据源应该是默认的。
    @ConfigurationProperties(prefix = "spring.datasource.one")  
    DataSource dsOne() {  
        return DruidDataSourceBuilder.create().build();  
    }  
  
  
    @Bean  
    @ConfigurationProperties(prefix = "spring.datasource.two")  
    DataSource dsTwo() {  
        return DruidDataSourceBuilder.create().build();  
    }  
}

@ConfigurationProperties是Spring Boot提供的类型安全的属性绑定,通过读取配置文件(例如:application.properties)中的前缀(例如:spring.datasource.one)属性去创建数据源,根据我们的配置我们将会有两个不同的数据源。

        5.新增JdbcTemplateConfig类:

接下来我们再通过JdbcTemplateConfig类根据不同的数据源,去创建不同的JdbcTemplate实例


@Configuration  
public class JdbcTemplateConfig {  
  
    @Bean  
    JdbcTemplate jdbcTemplateOne(@Qualifier("dsOne") DataSource dsOne) {  
        return new JdbcTemplate(dsOne);  
    }  
  
    @Bean  
    JdbcTemplate jdbcTemplateTwo(@Qualifier("dsTwo") DataSource dsTwo) {  
        return new JdbcTemplate(dsTwo);  
    }  
}


@Qualifier注解,表示按照名称查询。也就是就根据不同的数据源,创建了不同的JdbcTemplate实例。

        6.功能验证

通过Controller注入两个不同的JdbcTemplate,这两个JdbcTemplate对应了不同的数据源。

@RestController  
public class HelloController {  
    @Autowired  
    @Qualifier("jdbcTemplateOne")  
    JdbcTemplate jdbcTemplateOne;  
    @Resource(name = "jdbcTemplateTwo")  
    JdbcTemplate jdbcTemplateTwo;  
  
    @GetMapping("/test1")  
    public Integer getTest1() {  
        Integer count = jdbcTemplateOne.queryForObject("SELECT count(*) FROM user",Integer.class);  
        return count;  
    }  
    @GetMapping("/test2")  
    public Integer getTest2() {  
        Integer count = jdbcTemplateTwo.queryForObject("SELECT count(*) FROM fruit", Integer.class);  
        return count;  
    }

小蒋解释一下注入方式:

  1. 使用JDK提供的@Resource注解,通过byName方式注入。
  2. 使用Spring提供的@Autowrired注解,配合@Qualifier注解,两者联合方式注入。

(这两种注入方式本质上都是ByName,区别无非就是使用JDK提供的,还是使用Spring提供的而已)