Define Multiple DataSources in Spring

Introduction

This tutorial will show you how you can get a list of data sources using Spring framework. I will define multiple datasources in Spring. There may be situations where you need to define multiple datasources in Spring application.

Why do you need multiple DataSource? You might need to connect to multiple different databases from your same application. Then you need to define multiple datasources to insert or update in different database servers.

Related Posts:

So in this case you can have different datasource bean ids configured in Spring configuration class and You can use those datasources as per your needs in the different part of the application when required.

Here I am going to create a datasource holder class which will give you a list of all datasources available in the entire application.

Prerequisites

Eclipse 2020-06, At least Java 8, Gradle 6.5.1, Maven 3.6.3, Spring 5.2.8

Project Setup

You can create either gradle or maven based project in Eclipse. The name of the project is spring-multiple-datasources.

I have added two different database types, such as, MySQL and PostgreSQL because you may need to work different databases.

if you are creating gradle based project then use below build.gradle script:

plugins {
    id 'java-library'
}

repositories {
    jcenter()
}

dependencies {
	implementation 'org.springframework:spring-core:5.2.8.RELEASE'
	implementation 'org.springframework:spring-context:5.2.8.RELEASE'
    implementation 'org.springframework:spring-jdbc:5.2.8.RELEASE'
    implementation 'mysql:mysql-connector-java:8.0.17'
    implementation 'org.postgresql:postgresql:42.2.14'
    implementation 'javax.annotation:javax.annotation-api:1.3.2'
    
    //required for JDK 9 or above
    implementation 'javax.xml.bind:jaxb-api:2.4.0-b180830.0359'
}

If you are creating maven based project then you can use below pom.xml file:

<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.roytuts</groupId>
	<artifactId>spring-multiple-datasources</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>at least 1.8</java.version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-core</artifactId>
			<version>5.2.8.RELEASE</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.2.8.RELEASE</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>5.2.8.RELEASE</version>
		</dependency>
		
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.17</version>
		</dependency>
		
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<version>42.2.14</version>
		</dependency>
		
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>1.3.2</version>
		</dependency>
		
		<!--required only if jdk 9 or higher version is used-->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.4.0-b180830.0359</version>
		</dependency>
	</dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
                <configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

DataSource Configuration

Now I am going to configure datasources. First you need to have the configuration file. The configuration file contains the database setting for different servers.

Create a file jdbc.properties under classpath folder src/main/resources with the following details.

jdbc.mysql.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/roytuts
jdbc.mysql.username=root
jdbc.mysql.password=root

jdbc.postgresql.driverClassName=org.postgresql.Driver
jdbc.postgresql.url=jdbc:postgresql://localhost:5432/roytuts
jdbc.postgresql.username=root
jdbc.postgresql.password=root

Next I am going to create datsources bean and the bean for a class that finds all available datsources in the entire application.

package com.roytuts.spring.multiple.datasources.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import com.roytuts.spring.multiple.datasources.DataSources;

@Configuration
@PropertySource("classpath:jdbc.properties")
@ComponentScan(basePackages = "com.roytuts.spring.multiple.datasources.config")
public class Config {

	@Autowired
	private Environment environment;

	@Bean
	public DataSource dataSourceMysql() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();

		dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.mysql.driverClassName"));
		dataSource.setUrl(environment.getRequiredProperty("jdbc.mysql.url"));
		dataSource.setUsername(environment.getRequiredProperty("jdbc.mysql.username"));
		dataSource.setPassword(environment.getRequiredProperty("jdbc.mysql.password"));

		return dataSource;
	}

	@Bean
	public JdbcTemplate jdbcTemplateMysql() throws ClassNotFoundException {
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceMysql());

		return jdbcTemplate;
	}

	@Bean
	public DataSource dataSourcePostgresql() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();

		dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.postgresql.driverClassName"));
		dataSource.setUrl(environment.getRequiredProperty("jdbc.postgresql.url"));
		dataSource.setUsername(environment.getRequiredProperty("jdbc.postgresql.username"));
		dataSource.setPassword(environment.getRequiredProperty("jdbc.postgresql.password"));

		return dataSource;
	}

	@Bean
	public JdbcTemplate jdbcTemplatePostgresql() throws ClassNotFoundException {
		JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourcePostgresql());

		return jdbcTemplate;
	}

	@Bean
	public DataSources dataSources() {
		return new DataSources();
	}

}

The corresponding DataSources class is given below. Here I am using @PostConstruct annotation to execute the method once constructor is loaded and finding all available datasources and storing into a Map object.

package com.roytuts.spring.multiple.datasources;

import java.util.Map;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class DataSources {

	private Map<String, DataSource> dataSourceMap;

	@Autowired
	private ApplicationContext applicationContext;

	@PostConstruct
	public void init() {
		dataSourceMap = applicationContext.getBeansOfType(DataSource.class);
	}

	public Map<String, DataSource> getDataSources() {
		return dataSourceMap;
	}

}

Testing the Application

Next I am going to create a class having main method to load the required beans using ApplicationContext.

package com.roytuts.spring.multiple.datasources;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.roytuts.spring.multiple.datasources.config.Config;

public class SpringMultipleDataSourcesApp {

	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

		DataSources dataSources = context.getBean(DataSources.class);

		dataSources.getDataSources().forEach((k, v) -> System.out.println("Key: " + k + ", Value: " + v));

		((ConfigurableApplicationContext) context).close();
	}

}

Executing the above code will give you the following output:

Key: dataSourceMysql, Value: org.springframework.jdbc.datasource.DriverManagerDataSource@6200f9cb
Key: dataSourcePostgresql, Value: org.springframework.jdbc.datasource.DriverManagerDataSource@2002fc1d

Source Code

Download

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *