点击围观!腾讯 TAPD 助力金融行业研发提效、敏捷转型最佳实践! 了解详情
写点什么

在 Spring 中同时访问多种不同数据库

  • 2016-10-10
  • 本文字数:5344 字

    阅读完需:约 18 分钟

开发企业应用时我们常常遇到要同时访问多种不同数据库的问题,有时是必须把数据归档到某种数据仓库中,有时是要把数据变更推送到第三方数据库中。使用 Spring 框架时,使用单一数据库是非常容易的,但如果要同时访问多个数据库的话事件就变得复杂多了。

本文以在 Spring 框架下开发一个 SpringMVC 程序为例,示范了一种同时访问多种数据库的方法,而且尽量地简化配置改动。

搭建数据库

建议你也同时搭好两个数据库来跟进我们的示例。本文中我们用了 PostgreSQL 和 MySQL。

下面的脚本内容是在两个数据库中建表和插入数据的命令。

PostgreSQL

复制代码
CREATE TABLE usermaster (
id integer,
name character varying,
emailid character varying,
phoneno character varying(10),
location character varying
)
INSERT INTO usermaster(id, name, emailid, phoneno, location)
VALUES (1, 'name_postgres', 'email@email.com', '1234567890', 'IN');

MySQL

复制代码
CREATE TABLE `usermaster` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`emailid` varchar(20) DEFAULT NULL,
`phoneno` varchar(20) DEFAULT NULL,
`location` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
)
INSERT INTO `kode12`.`usermaster`
(`id`, `name`, `emailid`, `phoneno`, `location`)
VALUES
('1', 'name_mysql', 'test@tset.com', '9876543210', 'IN');

搭建项目

我们用 Spring Tool Suite ( STS ) 来构建这个例子:

  • 点击 File -> New -> Spring Starter Project。
  • 在对话框中输入项目名、Maven 坐标、描述和包信息等,点击 Next。
  • 在 boot dependency 中选择 Web,点击 Next。
  • 点击 Finish。STS 会自动按照项目依赖关系从 Spring 仓库中下载所需要的内容。

创建完的项目如下图所示:

接下来我们仔细研究一下项目中的各个相关文件内容。

pom.xml

pom 中包含了所有需要的依赖和插件映射关系。

代码:

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aegis</groupId>
<artifactId>MultipleDBConnect</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>MultipleDB</name>
<description>MultipleDB with Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath />
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

解释:

下面详细解释各种依赖关系的细节:

  • spring-boot-starter-web:为 Web 开发和 MVC 提供支持。
  • spring-boot-starter-test: 提供 JUnit、Mockito 等测试依赖。
  • spring-boot-starter-jdbc:提供 JDBC 支持。
  • postgresql:PostgreSQL 数据库的 JDBC 驱动。
  • mysql-connector-java:MySQL 数据库的 JDBC 驱动。

application.properties

包含程序需要的所有配置信息。在旧版的 Spring 中我们要通过多个 XML 文件来提供这些配置信息。

复制代码
server.port=6060
spring.ds_post.url =jdbc:postgresql://localhost:5432/kode12
spring.ds_post.username =postgres
spring.ds_post.password =root
spring.ds_post.driverClassName=org.postgresql.Driver
spring.ds_mysql.url = jdbc:mysql://localhost:3306/kode12
spring.ds_mysql.username = root
spring.ds_mysql.password = root
spring.ds_mysql.driverClassName=com.mysql.jdbc.Driver

解释:

“server.port=6060”声明你的嵌入式服务器启动后会使用 6060 端口(port.server.port 是 Boot 默认的标准端口)。

其他属性中:

  • 以“spring.ds_*”为前缀的是用户定义属性。
  • 以“spring.ds_post.*”为前缀的是为 PostgreSQL 数据库定义的属性。
  • 以“spring.ds_mysql.*”为前缀的是为 MySQL 数据库定义的属性。

MultipleDbApplication.java

复制代码
package com.aegis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public MultipleDbApplication {
public static void main(String[] args) {
SpringApplication.run(MultipleDbApplication.class, args);
}
}

这个文件包含了启动我们的 Boot 程序的主函数。注解“@SpringBootApplication”是所有其他 Spring 注解和 Java 注解的组合,包括:

复制代码
@Configuration
@EnableAutoConfiguration
@ComponentScan
@Target(value={TYPE})
@Retention(value=RUNTIME)
@Documented
@Inherited

其他注解:

复制代码
@Configuration
@EnableAutoConfiguration
@ComponentScan

上述注解会让容器通过这个类来加载我们的配置。

MultipleDBConfig.java

复制代码
package com.aegis.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
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 org.springframework.jdbc.core.JdbcTemplate;
@Configuration
public class MultipleDBConfig {
@Bean(name = "mysqlDb")
@ConfigurationProperties(prefix = "spring.ds_mysql")
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "mysqlJdbcTemplate")
public JdbcTemplate jdbcTemplate(@Qualifier("mysqlDb") DataSource dsMySQL) {
return new JdbcTemplate(dsMySQL);
}
@Bean(name = "postgresDb")
@ConfigurationProperties(prefix = "spring.ds_post")
public DataSource postgresDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "postgresJdbcTemplate")
public JdbcTemplate postgresJdbcTemplate(@Qualifier("postgresDb")
DataSource dsPostgres) {
return new JdbcTemplate(dsPostgres);
}
}

解释:

这是加了注解的配置类,包含加载我们的 PostgreSQL 和 MySQL 数据库配置的函数和注解。这也会负责为每一种数据库创建 JDBC 模板类。

下面我们看一下这四个函数:

复制代码
1 @Bean(name = "mysqlDb")
2 @ConfigurationProperties(prefix = "spring.ds_mysql")
3 public DataSource mysqlDataSource() {
4 return DataSourceBuilder.create().build();
5 }

上面代码第一行创建了 mysqlDb bean。
第二行帮助 @Bean 加载了所有有前缀 spring.ds_mysql 的属性。
第四行创建并初始化了 DataSource 类,并创建了 mysqlDb DataSource 对象。

复制代码
1 @Bean(name = "mysqlJdbcTemplate")
2 public JdbcTemplate jdbcTemplate(@Qualifier("mysqlDb") DataSource dsMySQL) {
3 return new JdbcTemplate(dsMySQL);
4 }

第一行以 mysqlJdbcTemplate 为名创建了一个 JdbcTemplate 类型的新 Bean。
第二行将第一行中创建的 DataSource 类型新参数传入函数,并以 mysqlDB 为 qualifier。
第三行用 DataSource 对象初始化 JdbcTemplate 实例。

复制代码
1 @Bean(name = "postgresDb")
2 @ConfigurationProperties(prefix = "spring.ds_post")
3 public DataSource postgresDataSource() {
4 return DataSourceBuilder.create().build();
5 }

第一行创建 DataSource 实例 postgresDb。
第二行帮助 @Bean 加载所有以 spring.ds_post 为前缀的配置。
第四行创建并初始化 DataSource 实例 postgresDb。

复制代码
1 @Bean(name = "postgresJdbcTemplate")
2 public JdbcTemplate postgresJdbcTemplate(@Qualifier("postgresDb")
DataSource dsPostgres) {
3 return new JdbcTemplate(dsPostgres);
4 }

第一行以 postgresJdbcTemplate 为名创建 JdbcTemplate 类型的新 bean。
第二行接受 DataSource 类型的参数,并以 postgresDb 为 qualifier。
第三行用 DataSource 对象初始化 JdbcTemplate 实例。

DemoController.java

复制代码
package com.aegis.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@Autowired
@Qualifier("postgresJdbcTemplate")
private JdbcTemplate postgresTemplate;
@Autowired
@Qualifier("mysqlJdbcTemplate")
private JdbcTemplate mysqlTemplate;
@RequestMapping(value = "/getPGUser")
public String getPGUser() {
Map<String, Object> map = new HashMap<String, Object>();
String query = " select * from usermaster";
try {
map = postgresTemplate.queryForMap(query);
} catch (Exception e) {
e.printStackTrace();
}
return "PostgreSQL Data: " + map.toString();
}
@RequestMapping(value = "/getMYUser")
public String getMYUser() {
Map<String, Object> map = new HashMap<String, Object>();
String query = " select * from usermaster";
try {
map = mysqlTemplate.queryForMap(query);
} catch (Exception e) {
e.printStackTrace();
}
return "MySQL Data: " + map.toString();
}
}

解释:

@RestController 类注解表明这个类中定义的所有函数都被默认绑定到响应中。

上面代码段创建了一个 JdbcTemplate 实例。@Qualifier 用于生成一个对应类型的模板。代码中提供的是 postgresJdbcTemplate 作为 Qualifier 参数,所以它会加载 MultipleDBConfig 实例的 jdbcTemplate(…) 函数创建的 Bean。

这样 Spring 就会根据你的要求来调用合适的 JDBC 模板。在调用 URL “/getPGUser”时 Spring 会用 PostgreSQL 模板,调用 URL “/getMYUser”时 Spring 会用 MySQL 模板。

复制代码
@Autowired
@Qualifier("postgresJdbcTemplate")
private JdbcTemplate postgresTemplate;

这里我们用 queryForMap(String query) 函数来使用 JDBC 模板从数据库中获取数据,queryForMap(…) 返回一个 map,以字段名为 Key,Value 为实际字段值。

演示

执行类 MultipleDbApplication 中的 main (…) 函数就可以看到演示效果。在你常用的浏览器中点击下面 URL:

URL: http://localhost:6060/getMYUser

上面的 URL 会查询 MySQL 数据库并以字符串形式返回数据。

Url: http://localhost:6060/getPGUser

上面的 URL 会查询 PostgreSQL 数据库并以字符串形式返回数据。

关于作者

Aaron Jacobson是个经验丰富的 Java Web 程序员,在外包与咨询公司 Technoligent 担任 Java 开发程序员 10 年以上。他的主要贡献包括 Java、Python、Asp.Net 和手机应用等一系列 Web 解决方案。可以通过 Twitter @Techno_Ligent 或 Facebook @TechnoLigent 联系他。

阅读英文原文 Working with Multiple Databases in Spring

2016-10-10 18:569383
用户头像

发布了 152 篇内容, 共 65.1 次阅读, 收获喜欢 62 次。

关注

评论

发布
暂无评论
发现更多内容

FreeNas安装、初始化和存储池设置

指剑

centos 11月月更 freenas

SAP 异常现象之同一个IDoc可以被POST两次触发2张不同的物料凭证

SAP虾客

SAP IDoc BD87

3.面向复杂度的架构设计模式

程序员小张

「架构实战营」

java培训学习中怎么来提升开发水平

小谷哥

ansible2.4安装和体验

程序员欣宸

DevOps ansible 11月月更

教你用JavaScript实现计数器

小院里的霍大侠

JavaScript 编程开发 初学者 入门实战

我们又重写了一个关键服务

Zilliz

人工智能 Milvus 向量数据库

看知识图谱如何解锁隐藏的营销利器

Neo4j 图无处不在

算法 neo4j 图数据库 知识图谱 图数据

DTSE Tech Talk 第13期:Serverless凭什么被誉为未来云计算范式?

华为云开发者联盟

云计算 后端 华为云

MobPush 推送查询API

MobTech袤博科技

为什么mysql不推荐使用雪花ID作为主键

京东科技开发者

MySQL 数据 雪花id 主键 自增

云安全系列4:解析云安全工具集

HummerCloud

云计算 云安全

又一创新!阿里云 Serverless 调度论文被云计算顶会 ACM SoCC 收录

Serverless Devs

如何通过链路追踪进行定时任务诊断

阿里巴巴云原生

阿里云 云原生 SchedulerX

前端培训程序员学习就业还有前途吗?

小谷哥

效能工具如何在企业规模化落地?|线上沙龙回顾

万事ONES

嵌入式系统概述及特点

timerring

嵌入式 11月月更

云小课|云小课教您如何选择Redis实例类型

华为云开发者联盟

云计算 后端 华为云

AI技术实践|用腾讯云慧眼微信浮层H5解决黄牛抢票问题

牵着蜗牛去散步

人工智能 腾讯云 腾讯 腾讯云AI

K3S +Helm+NFS最小化测试安装部署只需十分钟

京东科技开发者

Docker k8s 软件测试 k3s 应用程序

面试合集:数据库+数据结构+JVM+网络+JAVA+分布式+操作系统

钟奕礼

Java 程序员 java面试 java编程

企业号12月PK榜,等你参与!

InfoQ写作社区官方

热门活动

“读懂人话”,阿里AI总分首次超越人类成绩

云布道师

人工智能 阿里云

一个小而美的项目如何进行跨端选型

Onegun

移动端 跨端开发

企业网络“卫生”实用指南

SEAL安全

企业安全

我代码就加了一行log日志,结果引发了P1的线上事故

小小怪下士

Java 程序员 log 代码

参加大数据培训学习还来得及吗

小谷哥

在Spring中同时访问多种不同数据库_Java_Aaron Jacobson_InfoQ精选文章