Spring Boot中JdbcTemplate多数据源配置

作者简介:大家好,我是撸代码的羊驼,前阿里巴巴架构师,现某互联网公司CTO

联系v:sulny_ann(17362204968),加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

在《Spring Boot中JdbcTemplate源码分析》中讲到了自动配置相关的源代码实现。基于Spring Boot自动配置默认配置的组件,我们可以来自定义JdbcTemplate的实例化。而多数据源的配置就是在此基础上实例化多个数据源和JdbcTemplate。

下面,我们来看具体的源代码实现。

依赖类库

关于依赖类库与集成JdbcTemplate时的一样,Spring Boot版本2.2.2.RELEASE。

相关pom依赖如下:

<dependencies>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency>
    <!--数据库连接相关-->    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-jdbc</artifactId>    </dependency>    <dependency>        <groupId>mysql</groupId>        <artifactId>mysql-connector-java</artifactId>    </dependency>
    <dependency>        <groupId>org.projectlombok</groupId>        <artifactId>lombok</artifactId>        <optional>true</optional>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-test</artifactId>        <scope>test</scope>        <exclusions>            <exclusion>                <groupId>org.junit.vintage</groupId>                <artifactId>junit-vintage-engine</artifactId>            </exclusion>        </exclusions>    </dependency></dependencies>

spring-boot-starter-jdbc是集成jdbc的依赖,mysql-connector-java是基于mysql的依赖类库。lombok是简化代码的工具类,如果不需要可去掉,并去掉类中相关的注解。

spring-boot-starter-test为单元测试依赖的类库,这里单元测试使用的是junit5,注意使用方法与junit4差别比较大。

配置application

application.properties配置如下:​​​​​​​

spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=truespring.datasource.primary.username=rootspring.datasource.primary.password=root_123spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/spring1?serverTimezone=UTC&useUnicode=true\  &characterEncoding=utf-8&useSSL=truespring.datasource.secondary.username=rootspring.datasource.secondary.password=root_123spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver

既然是多数据源,肯定要配置多个数据源的配置。与单数据源配置基本形式差不多。

需要注意的是第一个配置项的key为:spring.datasource.primary.jdbc-url。与单数据源时使用的spring.datasource.url有所区别。不然,启动时会抛出异常。

多数据源对应的Java配置

下面就需要我们自己来实例化DataSource和JdbcTemplate。相关的实例化也可参看源码解析文章中Spring Boot的实例化方式。

这里,我们的实现如下:​​​​​​​

@Configurationpublic class DataSourceConfig {
  @Primary  @Bean(name = "primaryDataSource")  @ConfigurationProperties(prefix="spring.datasource.primary")  public DataSource primaryDataSource() {    return DataSourceBuilder.create().build();  }
  @Bean(name = "secondaryDataSource")  @ConfigurationProperties(prefix="spring.datasource.secondary")  public DataSource secondaryDataSource() {    return DataSourceBuilder.create().build();  }
  @Bean(name="primaryJdbcTemplate")  public JdbcTemplate primaryJdbcTemplate (@Qualifier("primaryDataSource")  DataSource dataSource ) {    return new JdbcTemplate(dataSource);  }
  @Bean(name="secondaryJdbcTemplate")  public JdbcTemplate  secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {    return new JdbcTemplate(dataSource);  }
}

@Configuration声明该类为配置类。

@Primary指定当出现多个相同类型的实例化对象时,以该注解标注的为默认的。

@Bean实例化Bean,并将其注入到容器当中。这里分别实例化了primaryDataSource和secondaryDataSource两个DataSource,以Bean的名称来区分。

@ConfigurationProperties将前缀为spring.datasource.primary和前缀为spring.datasource.secondary的配置属性设置到对应的DataSource中。

随后实例化了两个JdbcTemplate,直接通过new关键字创建,并且把对应的DataSource作为构造参数传入。

经过该配置文件的配置,便有了两个JdbcTemplate。

实体类

实体类如下:​​​​​​​

@Datapublic class Order {
  private int id;
  private String orderNo;
  private int amount;}

@Data为Lombok的注解,自动生成一些默认的方法,比如属性的getter/setter方法。

数据库

关于数据库的DDL如下:​​​​​​​

CREATE TABLE `tb_order` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `amount` int(11) NOT NULL DEFAULT '1',  `order_no` varchar(64) NOT NULL DEFAULT '',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

同样的表在两个数据库中进行创建。

接口定义

定义OrderService接口:​​​​​​​

public interface OrderService {
  /**   * 创建订单   * @param order 订单信息   * @return 记录数   */  int save(Order order);
  /**   * 保存到指定库   * @param order 订单信息   * @param jdbcTemplate jdbc   * @return   */  int save(Order order, JdbcTemplate jdbcTemplate);}

接口实现:​​​​​​​

@Service("orderService")public class OrderServiceImpl implements OrderService {
  @Resource  @Qualifier("primaryJdbcTemplate")  private JdbcTemplate jdbcTemplate;
  @Override  public int save(Order order) {    return jdbcTemplate.update("insert into tb_order(order_no, amount) values(?, ?)", order.getOrderNo(),        order.getAmount());  }
  @Override  public int save(Order order, JdbcTemplate secJdbcTemplate) {    if (secJdbcTemplate != null) {      return secJdbcTemplate.update("insert into tb_order(order_no, amount) values(?, ?)", order.getOrderNo(),          order.getAmount());    } else {      return jdbcTemplate.update("insert into tb_order(order_no, amount) values(?, ?)", order.getOrderNo(),          order.getAmount());    }  }}

在实现方法中,默认注入了主库的JdbcTemplate,同时在原来的save方法中新增了一个JdbcTemplate参数,可以根据是否传递该新的JdbcTemplate来决定使用哪个JdbcTemplate。

当然在此方法内也可以使用一个JdbcTemplate,然后根据参数动态的修改该JdbcTemplate指向的具体实现类。可以根据具体情况进行灵活运用。

单元测试

单元测试类如下:

@Slf4j@SpringBootTestclass OrderServiceTest {
  @Resource  private OrderService orderService;
  @Resource  @Qualifier("primaryJdbcTemplate")  private JdbcTemplate primaryJdbcTemplate;
  @Resource  @Qualifier("secondaryJdbcTemplate")  private JdbcTemplate secondaryJdbcTemplate;
  @Test  void save() {    Order order = new Order();    order.setOrderNo("N003");    order.setAmount(10000);    orderService.save(order, primaryJdbcTemplate);    orderService.save(order, secondaryJdbcTemplate);  }}

执行以上单元测试,两个库中的tb_order表分别插入了一条数据。关于其他增删改查操作,可参考保存方法进行扩展。

相关推荐
aloha_7895 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
阑梦清川10 小时前
JavaEE进阶---第一个SprintBoot项目创建过程&&&我的感受
java·java-ee·springboot
A-bodgie11 小时前
Spring 中的 Environment 对象
java·后端·spring·servlet·springboot
小布布的不14 小时前
MyBatis 返回 Map 或 List<Map>时,时间类型数据,默认为LocalDateTime,响应给前端默认含有‘T‘字符
前端·mybatis·springboot
小沈同学呀15 小时前
Mac M1 Docker创建Rocketmq集群并接入Springboot项目
macos·docker·java-rocketmq·springboot
东皋长歌2 天前
SpringBoot+ClickHouse集成
clickhouse·springboot
程序员徐师兄2 天前
基于 JavaWeb 的宠物商城系统(附源码,文档)
java·vue·springboot·宠物·宠物商城
果冻眼企鹅2 天前
常见用于从 HTTP 请求中提取数据的注解
springboot
你白勺男孩TT3 天前
Vue项目中点击按钮后浏览器屏幕变黑,再次点击恢复的解决方法
vue.js·vue·springboot
小云小白3 天前
springboot 传统应用程序,适配云原生改造
云原生·系统架构·k8s·springboot