9

【DB系列】JdbcTemplate之多数据源配置与使用

 3 years ago
source link: http://spring.hhui.top/spring-blog/2020/12/27/201227-SpringBoot系列JdbcTemplate之多数据源配置与使用/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

虽然我们前面的db系列教程更多的是基于单数据源的db操作,但是实际的业务开发中,难免会遇到一个项目配置多个数据源的情况,接下来本文将介绍一下多个数据源可以怎么配置,我们的JdbcTemplate又应该如何获取

I. 环境准备

1. 数据库相关

以mysql为例进行演示说明,因为需要多数据源,一个最简单的case就是一个物理库上多个逻辑库,本文是基于本机的mysql进行操作

创建数据库 teststory ,两个库下都存在一个表 money (同名同结构表,但是数据不同哦)

CREATE TABLE `money` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
  `money` int(26) NOT NULL DEFAULT '0' COMMENT '钱',
  `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

iqmEvaJ.jpg!mobile

2. 项目环境

本项目借助 SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA 进行开发

下面是核心的 pom.xml (源码可以再文末获取)

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
</dependencies>

配置文件信息 application.yml

# 数据库相关配置
spring:
  datasource:
    story:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password:
    test:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password:


# 日志相关
logging:
  level:
    root: info
    org:
      springframework:
        jdbc:
          core: debug

请注意上面的数据库配置,我们前面介绍的但数据库配置如下,它们层级并不一样,上面的配置需要我们自己额外进行加载解析

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password:

II. 多数据源支持

1. 数据源配置

SpringBoot帮我们省略了很多操作,单数据源时,在yaml文件中配置数据库相关信息之后,我们不需要任何其他操作,Spring会帮我们实例对应的 DataSource ,然后借助它来创建 JdbcTemplate

而多数据源则需要我们自己来额外处理了,请注意上面的配置信息,和默认的配置没什么差别,只是前缀多了一层,我们可以借助 @ConfigurationProperties 来加载配置文件

@Configuration
public class DataSourceConfiguration {

    @Primary
    @Bean(name = "storyDataSourceProperties")
    @ConfigurationProperties(prefix = "spring.datasource.story")
    public DataSourceProperties storyDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Primary
    @Bean(name = "storyDataSource")
    public DataSource storyDataSource(@Qualifier("storyDataSourceProperties") DataSourceProperties storyDataSourceProperties) {
        return storyDataSourceProperties.initializeDataSourceBuilder().build();
    }

    @Bean(name = "testDataSourceProperties")
    @ConfigurationProperties(prefix = "spring.datasource.test")
    public DataSourceProperties testDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean(name = "testDataSource")
    public DataSource testDataSource(@Qualifier("testDataSourceProperties") DataSourceProperties testDataSourceProperties) {
        return testDataSourceProperties.initializeDataSourceBuilder().build();
    }
}

配置代码如上,一个是将数据源配置映射为bean DataSourceProperties , 一个是根据数据源配置实例化 DataSource

此外两个 @Primary 注解,主要是为了设置默认的数据源

2. JdbcTemplate实例化

数据源已经获取到之后,再实例化 JdbcTemplate 就很简单了,除了直接声明bean之外,也可以基于 DataSource 来手动创建临时对象,下面给出两种使用姿势

定义对应的 bean ,对于业务使用更友好

@Bean("storyJdbcTemplate")
public JdbcTemplate storyJdbcTemplate(@Qualifier("storyDataSource") DataSource storyDataSource) {
    return new JdbcTemplate(storyDataSource);
}

@Bean("testJdbcTemplate")
public JdbcTemplate testJdbcTemplate(@Qualifier("testDataSource") DataSource testDataSource) {
    return new JdbcTemplate(testDataSource);
}

借助 ApplicationContext 来实例化JdbcTemplate,使用更灵活

@Service
public class JdbcServer implements ApplicationContextAware {

    private JdbcTemplate storyJdbcTemplate;

    private JdbcTemplate testJdbcTemplate;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, DataSource> map = applicationContext.getBeansOfType(DataSource.class);
        System.out.println(map);
        storyJdbcTemplate = new JdbcTemplate(map.get("storyDataSource"));
        testJdbcTemplate = new JdbcTemplate(map.get("testDataSource"));
    }
}

3. 测试case

最后简单测试一下上面创建的两个 JdbcTemplate 是否访问不同的数据库

public void query() {
    List<Map<String, Object>> storyRes = storyJdbcTemplate.queryForList("select * from money where id in (1, 1000)");
    List<Map<String, Object>> testRes = testJdbcTemplate.queryForList("select * from money where id in (1, 1000)");
    System.out.println(storyRes);
    System.out.println("--------------");
    System.out.println(testRes);
}

启动类如下

@SpringBootApplication
public class Application {

    public Application(JdbcServer jdbcServer) {
        jdbcServer.query();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

MJnaEnf.jpg!mobile

相同的sql,获取的结果并不一样,分别从两个库中获取的数据

4. 小结

使用多数据源,比较简单的思路就是自定义配置的加载方式,获取不同的 DataSourceProperties 对象,然后基于它来创建 DataSource 实例

利用 JdbcTemplate 来操作db的应用场景,直接选择不同的数据源 Datasource 就行了

当然实际的项目中,我们一般会借助 HerbernateMyabtisJooq 等orm框架,那么使用orm时,多数据源又应该怎么处理呢? (请持续关注,相关博文即将上线)

II. 其他

0. 项目

系列博文

项目源码

1. 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

ri6Vj2M.png!mobile

打赏 如果觉得我的文章对您有帮助,请随意打赏。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK