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

相关推荐
下次再写12 小时前
深入浅出微服务架构:从理论到Spring Boot实战
java·微服务·springboot·springcloud·架构设计·后端开发·分布式系统
牛奶咖啡1314 小时前
CI/CD——在jenkins中构建流程实现springboot项目的自动化构建与部署
java·ci/cd·k8s·jenkins·springboot·springboot制作镜像·使用源码项目制作镜像
凤山老林15 小时前
慢SQL治理:索引优化实战指南——从定位到优化的完整解决方案
java·sql·springboot·慢sql治理·sql 性能优化
哆啦A梦15883 天前
01, 前端vue3框架的快速搭建以及项目工程的讲解
前端·vue3·springboot
桃花键神4 天前
【2026精品项目】基于SpringBoot3+Vue3的校园小卖铺系统(包含源码+项目文档+SQL脚本+部署教程)
数据库·sql·vue·毕业设计·springboot
洛阳泰山4 天前
Maxkb4j集成sqlbot MCP实现企业智能问数智能体
java·ai·springboot·agent·智能问数
zc.z5 天前
基于 LangChain4j 的 RAG 工作流智能体实战
langchain·大模型·springboot·rag智能体
suweijie7686 天前
Nacos配置读取异常排查与解决指南
微服务·nacos·springboot·配置中心·问题排查
程序员老邢6 天前
【产品底稿 12】工程架构最终定型:完整模块拆分、分包规范、层级依赖与开发规约全清单
微服务·架构·springboot·多模块·技术债务
abcnull6 天前
Springboot+Vue2的Web项目小白入门Demo快速学习!
java·elementui·vue·maven·springboot·web·小白