BT

Diffuser les Connaissances et l'Innovation dans le Développement Logiciel d'Entreprise

Contribuez

Sujets

Sélectionner votre région

Accueil InfoQ Articles Utiliser Plusieurs Bases de Données dans Spring

Utiliser Plusieurs Bases de Données dans Spring

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.

Evaluer cet article

Pertinence
Style

Contenu Éducatif

BT