手动创建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;
}
小蒋解释一下注入方式:
- 使用JDK提供的@Resource注解,通过byName方式注入。
- 使用Spring提供的@Autowrired注解,配合@Qualifier注解,两者联合方式注入。
(这两种注入方式本质上都是ByName,区别无非就是使用JDK提供的,还是使用Spring提供的而已)