Spring Boot中手动实例化 `JdbcTemplate` 并指定 数据源

一、核心前提:确保 sourceDataSource 已被Spring容器管理

手动实例化 JdbcTemplate 的前提是 sourceDataSource 必须是一个有效的 DataSource 实例(通常需纳入Spring容器管理,保证数据源配置生效、连接池正常工作)

1. 先配置 sourceDataSource 数据源(application.yml/application.properties)

application.yml 为例,配置数据源信息(以MySQL为例,适配国产数据库可替换驱动与URL):

yaml 复制代码
# 数据源配置(sourceDataSource)
spring:
  datasource:
    source:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/source_db?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
      # 连接池配置(默认HikariCP,Spring Boot内置)
      hikari:
        maximum-pool-size: 10
        minimum-idle: 2
        connection-timeout: 30000
2. 配置 sourceDataSource 实例(注入Spring容器)

通过配置类将 sourceDataSource 注册为Spring Bean,供后续实例化 JdbcTemplate 使用:

java 复制代码
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {

    /**
     * 配置sourceDataSource,纳入Spring容器管理
     * @return 数据源实例
     */
    @Bean(name = "sourceDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.source") // 绑定yml中的配置前缀
    @Primary // 若有多个数据源,指定默认数据源(可选)
    public DataSource sourceDataSource() {
        // Spring Boot默认使用HikariCP连接池,直接构建即可
        return new HikariDataSource();
    }
}

二、三种实例化 JdbcTemplate 的方式

方式1:手动直接实例化(非推荐,适用于临时测试/非容器管理场景)

直接通过 new 关键字创建 JdbcTemplate,传入 sourceDataSource 实例:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Component
public class TestJdbcComponent {

    // 从Spring容器中注入sourceDataSource
    @Autowired
    @Qualifier("sourceDataSource") // 若数据源Bean有名称,需指定Qualifier
    private DataSource sourceDataSource;

    // 手动实例化JdbcTemplate
    public JdbcTemplate getSourceJdbcTemplate() {
        // 直接传入sourceDataSource创建JdbcTemplate实例
        JdbcTemplate jdbcTemplate = new JdbcTemplate(sourceDataSource);
        // 可选:配置JdbcTemplate属性(如查询超时时间)
        jdbcTemplate.setQueryTimeout(30); // 查询超时30秒
        return jdbcTemplate;
    }

    // 测试使用
    public void testQuery() {
        JdbcTemplate jdbcTemplate = getSourceJdbcTemplate();
        String sql = "SELECT COUNT(*) FROM user";
        Integer count = jdbcTemplate.queryForObject(sql, Integer.class);
        System.out.println("用户总数:" + count);
    }
}
方式2:将 JdbcTemplate 注册为Spring Bean(推荐,全局复用)

将实例化后的 JdbcTemplate 注入Spring容器,供整个项目复用(无需重复创建):

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
public class JdbcTemplateConfig {

    /**
     * 实例化source对应的JdbcTemplate,注册为Spring Bean
     * @param sourceDataSource 自动注入容器中的sourceDataSource
     * @return JdbcTemplate实例
     */
    @Bean(name = "sourceJdbcTemplate")
    public JdbcTemplate sourceJdbcTemplate(@Qualifier("sourceDataSource") DataSource sourceDataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(sourceDataSource);
        // 可选配置
        jdbcTemplate.setQueryTimeout(30);
        jdbcTemplate.setIgnoreWarnings(true);
        return jdbcTemplate;
    }
}

使用时直接注入 JdbcTemplate 即可

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.jdbc.core.JdbcTemplate;

@Service
public class UserService {

    // 注入已实例化的sourceJdbcTemplate
    @Autowired
    @Qualifier("sourceJdbcTemplate")
    private JdbcTemplate sourceJdbcTemplate;

    public Integer getUserCount() {
        String sql = "SELECT COUNT(*) FROM user";
        return sourceJdbcTemplate.queryForObject(sql, Integer.class);
    }
}
方式3:Spring Boot自动配置(单数据源场景,最简)

若项目只有 sourceDataSource 一个数据源,Spring Boot会自动实例化 JdbcTemplate ,无需手动 new,直接注入即可使用:

java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.jdbc.core.JdbcTemplate;

@Service
public class OrderService {

    // Spring Boot自动配置的JdbcTemplate,默认使用主数据源(sourceDataSource)
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public String getOrderName(Long orderId) {
        String sql = "SELECT order_name FROM `order` WHERE id = ?";
        return jdbcTemplate.queryForObject(sql, new Object[]{orderId}, String.class);
    }
}

三、多数据源场景:实例化多个 JdbcTemplate

若项目存在多个数据源(如 sourceDataSourcetargetDataSource),可分别实例化对应的 JdbcTemplate

java 复制代码
@Configuration
public class MultiJdbcTemplateConfig {

    // 数据源1:sourceDataSource
    @Bean(name = "sourceDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.source")
    public DataSource sourceDataSource() {
        return new HikariDataSource();
    }

    // 数据源2:targetDataSource
    @Bean(name = "targetDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.target")
    public DataSource targetDataSource() {
        return new HikariDataSource();
    }

    // JdbcTemplate1:对应sourceDataSource
    @Bean(name = "sourceJdbcTemplate")
    public JdbcTemplate sourceJdbcTemplate(@Qualifier("sourceDataSource") DataSource sourceDataSource) {
        return new JdbcTemplate(sourceDataSource);
    }

    // JdbcTemplate2:对应targetDataSource
    @Bean(name = "targetJdbcTemplate")
    public JdbcTemplate targetJdbcTemplate(@Qualifier("targetDataSource") DataSource targetDataSource) {
        return new JdbcTemplate(targetDataSource);
    }
}

使用时通过 @Qualifier 指定对应的 JdbcTemplate

java 复制代码
@Service
public class DataSyncService {

    @Autowired
    @Qualifier("sourceJdbcTemplate")
    private JdbcTemplate sourceJdbcTemplate;

    @Autowired
    @Qualifier("targetJdbcTemplate")
    private JdbcTemplate targetJdbcTemplate;

    // 从源数据源查询,写入目标数据源
    public void syncUser() {
        // 源数据源查询
        String querySql = "SELECT id, username FROM user";
        List<Map<String, Object>> userList = sourceJdbcTemplate.queryForList(querySql);

        // 目标数据源写入
        String insertSql = "INSERT INTO user (id, username) VALUES (?, ?)";
        for (Map<String, Object> user : userList) {
            targetJdbcTemplate.update(insertSql, user.get("id"), user.get("username"));
        }
    }
}

四、注意事项

  1. 避免重复实例化 :手动 new JdbcTemplate 会导致每次创建新实例,建议将其注册为Spring Bean(单例模式),全局复用;
  2. 数据源必须有效 :确保 sourceDataSource 配置正确(URL、用户名、密码无误),驱动已引入(如MySQL驱动需在pom.xml中添加依赖);
  3. 国产数据库适配 :若使用达梦/人大金仓等国产数据库,需替换驱动类(如达梦:dm.jdbc.driver.DmDriver)和URL(如 jdbc:dm://localhost:5236/source_db);
  4. 连接池配置:优先使用Spring Boot内置的HikariCP连接池,合理配置最大连接数、最小空闲数,避免连接泄露;
  5. 异常处理 :使用 JdbcTemplate 时需捕获 DataAccessException 异常,处理数据库连接失败、SQL语法错误等问题。

总结

  1. 核心步骤:先配置并注入 sourceDataSource,再通过 new JdbcTemplate(sourceDataSource) 实例化;
  2. 推荐方式:将 JdbcTemplate 注册为Spring Bean(@Bean),通过 @Autowired+@Qualifier 注入使用,支持多数据源隔离;
  3. 单数据源简化:Spring Boot自动配置 JdbcTemplate,直接注入即可,无需手动实例化;
  4. 关键保障:确保数据源配置有效、驱动已引入,避免重复实例化造成资源浪费。
相关推荐
llz_1122 小时前
web-第二次课后作业
前端·后端·web
AI人工智能+电脑小能手7 小时前
【大白话说Java面试题 第87题】【Mysql篇】第17题:分布式事务的实现原理?
java·数据库·分布式·mysql·面试
红尘散仙7 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
来杯@Java8 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记9 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥9 小时前
匿名函数 lambda + 高阶函数
java·python·算法
会编程的土豆9 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
東雪木9 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
adrninistrat0r9 小时前
Java调用链MCP分析工具
java·python·ai编程
喵个咪9 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm