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表分别插入了一条数据。关于其他增删改查操作,可参考保存方法进行扩展。

相关推荐

  1. Spring BootJdbcTemplate数据配置

    2023-12-12 06:20:06       41 阅读
  2. Springboot实现配置数据

    2023-12-12 06:20:06       39 阅读
  3. Springboot JPA实现数据配置

    2023-12-12 06:20:06       31 阅读
  4. SpringBoot数据配置及使用

    2023-12-12 06:20:06       12 阅读
  5. SpringBoot基于注解形式配置数据@DS

    2023-12-12 06:20:06       29 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-12 06:20:06       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-12 06:20:06       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-12 06:20:06       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-12 06:20:06       18 阅读

热门阅读

  1. Jenkins:持续集成与持续交付的自动化利器

    2023-12-12 06:20:06       38 阅读
  2. 运筹学经典问题(一):指派问题

    2023-12-12 06:20:06       35 阅读
  3. 字符串相似度计算:Jaro-Winkler算法实现

    2023-12-12 06:20:06       43 阅读
  4. Docker笔记:Docker中简单配置Mysql/Redis/Mongodb容器

    2023-12-12 06:20:06       38 阅读
  5. uniapp点击图片预览功能?

    2023-12-12 06:20:06       42 阅读
  6. 排序算法——归并排序

    2023-12-12 06:20:06       35 阅读
  7. 在gen_server使用ets实例演示

    2023-12-12 06:20:06       32 阅读
  8. final的安全发布

    2023-12-12 06:20:06       35 阅读