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.
Le script ci-dessous montre une déclaration de création et d'insertion pour les deux fournisseurs de bases de données.
PostgreSQL
id integer,
MySQL
VALUES
pom.xml
Le POM contient toutes les déclarations de dépendances et de plugins.
Code
<
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
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 :
package com.aegis;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public MultipleDbApplication {
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
@Bean(name = "mysqlDb")
@ConfigurationProperties(prefix = "spring.ds_mysql")
return DataSourceBuilder.create().build();
@Bean(name = "mysqlJdbcTemplate")
@Bean(name = "postgresDb")
@ConfigurationProperties(prefix = "spring.ds_post")
return DataSourceBuilder.create().build();
@Bean(name = "postgresJdbcTemplate")
DataSource 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.
1 @Bean(name = "mysqlDb")
2 @ConfigurationProperties(prefix = "spring.ds_mysql")
4 return DataSourceBuilder.create().build();
5 }
La ligne 2 aide le @Bean à charger toutes les propriétés qui ont comme préfixe spring.ds_mysql.
1 @Bean(name = "mysqlJdbcTemplate")
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.
2 @ConfigurationProperties(prefix = "spring.ds_post")
4 return DataSourceBuilder.create().build();
5 }
La ligne 2 aide le @Bean à charger toutes les propriétés qui ont comme préfixe spring.ds_post.
1 @Bean(name = "postgresJdbcTemplate")
DataSource dsPostgres) {
4 }
La ligne 2 accepte une DataSource comme argument ayant comme qualifiant postgresDb, créé ci-dessus.
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
@Autowired
@Qualifier("postgresJdbcTemplate")
@Autowired
@Qualifier("mysqlJdbcTemplate")
@RequestMapping(value = "/getPGUser")
try {
map = postgresTemplate.queryForMap(query);
} catch (Exception e) {
e.printStackTrace();
@RequestMapping(value = "/getMYUser")
try {
map = mysqlTemplate.queryForMap(query);
} catch (Exception e) {
e.printStackTrace();
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")
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.