Lors du développement d'applications d'entreprise, nous sommes souvent confrontés à la problématique d'accès à plusieurs bases de données. Peut-être notre application doit archiver les données dans un quelconque entrepôt de données, ou peut-être doit elle propager des données dans une certaine base de données tiers. Avec Spring, il est assez facile de définir une source de données commune, mais il est plus délicat d'introduire plusieurs sources de données.
Dans cet article, nous allons réaliser une démo technique pour accéder facilement à plusieurs bases de données dans des applications Spring Boot avec configuration minimum, en développant une application Spring MVC basée sur Spring Boot.
Mise en place de la base de données
Pour suivre cette démonstration, nous vous suggérons d'avoir deux bases de données disponibles ; dans cet article, nous allons utiliser PostgreSQL et MySQL.
Le script ci-dessous montre une déclaration de création et d'insertion pour les deux fournisseurs de bases de données.
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');
Mise en place du projet
Spring Tools Suite (STS) sera utilisé pour le développement de cette démo :
- Cliquez sur Fichier -> Nouveau -> Projet Spring Starter.
- Dans la boîte de dialogue, remplissez le nom du projet, les coordonnées Maven, la description et les informations de package, puis cliquez sur Suivant.
- Pour les dépendances de Boot, sélectionnez Web puis cliquez sur Suivant.
- Cliquez sur Terminer. STS va télécharger le projet depuis le dépôt Spring avec votre dépendance.
Le projet doit avoir cette apparence :
Maintenant, regardons d'un peu plus près chaque fichier en détail.
pom.xml
Le POM contient toutes les déclarations de dépendances et de plugins.
Code
<?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>
Explication
Le tableau suivant détaille toutes les dépendances :
Dépendance | Détail |
---|---|
spring-boot-starter-web | Fournit le support pour le développement Web et MVC |
spring-boot-starter-test | Fournit les dépendances de test comme JUnit, Mockito, etc |
spring-boot-starter-jdbc | Fournit le support de JDBC |
Postgresql | Pilote JDBC pour la base de données PostgreSQL |
mysql-connector-java | Pilote JDBC pour la base de données MySQL |
application.properties
Contient toute la configuration de l'application Boot (dans une application Spring, nous fournirions cette configuration en utilisant plusieurs fichiers 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
Explication
server.port=6060
déclare que votre serveur embarqué démarrera sur le port 6060 (server.port
est une propriété standard fournie par Boot).
Les autres propriétés, préfixées par spring.ds_*
sont définies par l'utilisateur :
- Les propriétés préfixées par
spring.ds_post.*
sont utilisées pour définir la configuration de la base de données PostgreSQL. - Les propriétés préfixées par
spring.ds_mysql.*
sont utilisées pour définir la configuration de la base de données 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);
}
}
Ce fichier comprend notre méthode principale pour le lancement de notre application Boot. L'annotation @SpringBootApplication est une combinaison d'autres annotations Java et Spring y compris :
@Configuration
@EnableAutoConfiguration
@ComponentScan
@Target(value={TYPE})
@Retention(value=RUNTIME)
@Documented
@Inherited
Annotations supplémentaires :
@Configuration
@EnableAutoConfiguration
@ComponentScan
Il s'agit d'annotations Spring qui indiquent au container de scanner cette classe et de charger notre configuration.
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);
}
}
Explication
Il s'agit de la classe de configuration annotée qui contient les fonctions et les annotations pour charger la configuration PostgreSQL
et MySQL
. Elle est également responsable de la création de l'instance de JDBCTemplate
pour chacune.
Examinons chacune de ces quatre fonctions :
1 @Bean(name = "mysqlDb")
2 @ConfigurationProperties(prefix = "spring.ds_mysql")
3 public DataSource mysqlDataSource() {
4 return DataSourceBuilder.create().build();
5 }
La ligne 1 de l'extrait ci-dessus crée le bean mysqlDb
.
La ligne 2 aide le @Bean
à charger toutes les propriétés qui ont comme préfixe spring.ds_mysql
.
La ligne 4 crée et initialise la classe DataSource
et crée l'objet mysqlDbDataSource
.
1 @Bean(name = "mysqlJdbcTemplate")
2 public JdbcTemplate jdbcTemplate(@Qualifier("mysqlDb") DataSource dsMySQL) {
3 return new JdbcTemplate(dsMySQL);
4 }
La ligne 1 crée un nouveau bean de type JdbcTemplate
avec comme nom mysqlJdbcTemplate
.
La ligne 2 accepte un argument de type DataSource
ayant comme qualifiant mysqlDB
, qui a été créé en ligne 1 du premier extrait de code.
La ligne 3 initialise une instance de JdbcTemplate
avec l'aide de l'objet DataSource
.
1 @Bean(name = "postgresDb")
2 @ConfigurationProperties(prefix = "spring.ds_post")
3 public DataSource postgresDataSource() {
4 return DataSourceBuilder.create().build();
5 }
La ligne 1 de l'extrait ci-dessus crée l'instance postgresDb DataSource
.
La ligne 2 aide le @Bean
à charger toutes les propriétés qui ont comme préfixe spring.ds_post
.
La ligne 4 crée et initialise l'instance postgresDb DataSource
.
1 @Bean(name = "postgresJdbcTemplate")
2 public JdbcTemplate postgresJdbcTemplate(@Qualifier("postgresDb")
DataSource dsPostgres) {
3 return new JdbcTemplate(dsPostgres);
4 }
La ligne 1 crée un nouveau bean de type JdbcTemplate
nommé postgresJdbcTemplate
.
La ligne 2 accepte une DataSource
comme argument ayant comme qualifiant postgresDb
, créé ci-dessus.
La ligne 2 initialise une instance de JdbcTemplate
avec l'aide de l'objet DataSource
.
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();
}
}
Explication
Cette annotation de classe @RestController
indique que les résultats de toutes les méthodes déclarées dans cette classe seront liés par défaut au corps de la réponse.
L'extrait de code ci-dessus crée une instance de JdbcTemplate
. @Qualifier
contribue à générer un modèle du type spécifié. postgresJdbcTemplate
est fourni comme argument de qualifier de telle manière qu'il tente de charger le bean créé par la méthode jdbcTemplate (...)
de l'instance MultipleDBConfig
.
Spring invoquera désormais le template jdbc approprié en fonction de votre requête. A l'appel de l'URL /getPGUser
, Spring utilisera le template Postgres ; sur appel de /getMYUser
, Spring utilisera le template MySQL.
@Autowired
@Qualifier("postgresJdbcTemplate")
private JdbcTemplate postgresTemplate;
On a utilisé la méthode queryForMap(String query)
pour récupérer les données de la base en utilisant le template jdbc. La méthode queryForMap(…)
retourne un dictionnaire avec pour clé le nom de la colonne et associé à la valeur actuelle de la colonne.
Démo
Pour lancer la démo, exécutez la méthode main(...)
de la classe MultipleDbApplication
. Puis accédez à l'URL ci-dessous avec votre navigateur favori :
http://localhost:6060/getMYUser
L'invocation de cette URL requêtera la base de données utilisateur MySQL et retournera les données en tant que chaîne de caractères.
http://localhost:6060/getPGUser
L'invocation de cette URL requêtera la base de données utilisateur PostgresSQL et retournera les données en tant que chaîne de caractères.
A propos de l'Auteur
Aaron Jacobson est un vétéran dans le domaine du développement web Java, ayant travaillé comme développeur Java pour la firme de consulting/outsouring Technoligent pour les 10 dernières années. Ses contributions majeures comprennent une collection de solutions web pour Java, Python, Asp.Net et des apps mobile, entre autres. Vous pouvez suivre Aaron sur Twitter @Techno_Ligent and sur Facebook @TechnoLigent.