DEV Community

Separating data into different databases is a typical approach in the microservices world. This means that each backend usually needs to access only its limited database. At the same time, a backend application may need to use more than one database. This is why you can set up multiple datasources in Spring Boot.
In this step-by-step tutorial, you will learn how to configure Spring Boot Data 3 to work with many databases.
Getting Started
Suppose your Spring Boot RESTful backend needs to connect to the following two databases:
-
account
: A MySQL database containing user data -
company
: A PostgreSQL database storing company data
The databases rely on two different RDBMS technologies and might even be on two different servers.
For the sake of simplicity, suppose that both databases has a single table. account
has the user
table and company
has the product
table. The goal here is to create a Spring Boot app that can use both databases. Let’s learn how to do it!
Keep in mind that this is just a sample scenario and the proposed solution can easily be extended to an indefinite number of databases, regardless of their DBMS technology.
Configuring Multiple Datasources in JPA 3
Follow this step-by-step tutorial and learn how to configure a Spring Boot 3 project to work with different databases in JPA.
Prerequisites
Before getting started, you need to add the following dependencies to your Spring Boot 3 project:
If you are a Maven user, add the lines below to your pom.xml
file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
Otherwise, if you are Gradle user, verify that build.gradle
contains:
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.mysql:mysql-connector-j'
implementation 'org.postgresql:postgresql'
The last two dependencies are the PostgreSQL and MySQL drivers, respectively. These allow you to connect to MySQL and PostgreSQL servers. Make sure to add the right drivers to your project’s dependencies according to the database technologies your backend relies on.
You now have everything you need to set up multiple datasources in Spring Boot. Time to learn how to do it!
1. Mapping Your Entities
Create an entities
package and split it into the following two subpackages:
-
account
: Will contain all MySQL database entities -
company
: Will contain all PostgreSQL database entities
Define the User
and Product
JPA entities and place them in the right subpackage.
2. Defining the Datasource Connection Properties
Add the connection info for the two target datasources to your application.properties
file:
spring.datasource.account.url=jdbc:mysql://<MYSQL_DB_URL>/account
spring.datasource.account.username=<MYSQL_USERNAME>
spring.datasource.account.password=<MYSQL_PASSWORD>
spring.datasource.account.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.company.url=jdbc:postgresql://<POSTGRESQL_DB_CONNECTION_URL>/company
spring.datasource.company.username=<POSTGRESQL_USERNAME>
spring.datasource.company.password=<POSTGRESQL_PASSWORD>
spring.datasource.company.driver-class-name=org.postgresql.Driver
Replace all <___>
parameters with the right strings. Note that account
and company
after spring.datasource
are two custom options with the same name as the database they refer to.
3. Defining the Datasource Configuration Files
The info defined above can be used to create a database connection through a custom Spring Boot configuration file.
This is what the @Configuration
file for the account
database looks like:
package com.dbvis.demo.configs;
import com.dbvis.demo.entities.account.User;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Objects;
@Configuration
@EnableJpaRepositories(
basePackages = "com.dbvis.demo.repositories.account",
entityManagerFactoryRef = "accountEntityManagerFactory",
transactionManagerRef = "accountTransactionManager"
)
@EnableTransactionManagement
public class AccountDataSourceConfig {
/**
* Initialize a DataSourceProperties bean by reading the
* datasource info from "spring.datasource.account.*" configs
* in application.properties
*/
@Primary
@Bean
@ConfigurationProperties("spring.datasource.account")
public DataSourceProperties accountDataSourceProperties() {
return new DataSourceProperties();
}
/**
* Create the datasource for the "account" database
* using accountDataSourceProperties
*/
@Primary
@Bean
@ConfigurationProperties("spring.datasource.account.configuration")
public DataSource accountDataSource() {
return accountDataSourceProperties()
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
/**
* Configure Hibernate's EntityManager object
* to look for Entity classes inside the "com.dbvis.entities.account" package
*/
@Primary
@Bean(name = "accountEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean accountEntityManagerFactory(
EntityManagerFactoryBuilder builder,
DataSource dataSource
) {
return builder
.dataSource(accountDataSource())
.packages(User.class)
.build();
}
/**
* Create a transaction manager for the EntityManager object created with
* the "accountEntityManagerFactory" bean
*/
@Primary
@Bean
public PlatformTransactionManager accountTransactionManager(
@Qualifier("accountEntityManagerFactory")
LocalContainerEntityManagerFactoryBean accountEntityManagerFactory
) {
return new JpaTransactionManager(
Objects.requireNonNull(
accountEntityManagerFactory.getObject()
)
);
}
}
This file reads the account
connection info from application.properties
to instantiate a DataSource
bean. Then, it uses to create a valid EntityManager
and TransactionManager
. These two objects are what you need to handle a connection to a database. Check out the official documentation to learn more about how data access works in Spring Boot.
Note the use of the @Bean
name
property and @Qualifier
annotation to tell Spring Boot what specific bean to use. Also, notice that the scope of the EntityManager
gets restricted to the package containing the User
entity, which is the account
subpackage.
Similarly, you need to define a @Configuration
file for company
:
package com.dbvis.demo.configs;
import com.dbvis.demo.entities.company.Product;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.Objects;
@Configuration
@EnableJpaRepositories(
basePackages = "com.dbvis.demo.repositories.company",
entityManagerFactoryRef = "companyEntityManagerFactory",
transactionManagerRef = "companyTransactionManager"
)
public class CompanyDataSourceConfig {
/**
* Initialize a DataSourceProperties bean by reading the
* datasource info from "spring.datasource.company.*" configs
* in application.properties
*/
@Bean
@ConfigurationProperties("spring.datasource.company")
public DataSourceProperties companyDataSourceProperties() {
return new DataSourceProperties();
}
/**
* Create the datasource for the "company" database
* using companyDataSourceProperties
*/
@Bean
@ConfigurationProperties("spring.datasource.company.configuration")
public DataSource companyDataSource() {
return companyDataSourceProperties()
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
/**
* Configure Hibernate's EntityManager object
* to look for Entity classes inside the "com.dbvis.entities.company" package
*/
@Bean(name = "companyEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean companyEntityManagerFactory(
EntityManagerFactoryBuilder builder
) {
return builder
.dataSource(companyDataSource())
.packages(Product.class)
.build();
}
/**
* Create a transaction manager for the EntityManager object created with
* the "companyEntityManagerFactory" bean
*/
@Bean
public PlatformTransactionManager companyTransactionManager(
@Qualifier("companyEntityManagerFactory")
LocalContainerEntityManagerFactoryBean companyEntityManagerFactory
) {
return new JpaTransactionManager(
Objects.requireNonNull(
companyEntityManagerFactory.getObject()
)
);
}
}
The main difference is that this config file refers to the company
values in application.properties
. Also, its Spring Boot beans are not marked with @Primary
. This is because only one DataSource
connection must be specified as primary.
If you forget to mark one of the two connections as primary, Spring Boot will fail with the following error:
Parameter 0 of method companyEntityManagerFactory in com.dbvis.demo.configs.AAProductDataSourceConfig required a bean of type 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' that could not be found.
4. Creating the JPA Repositories
It only remains to define some Spring Data repositories. This will help you perform CRUD operations on your tables.
Create a repositories
packages. Then, consider splitting the package into as many subpackage as the number of databases you need to connect to.
You can define a UserRepository
as below:
package com.dbvis.demo.repositories.account;
import com.dbvis.demo.entities.account.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {}
Note that the JpaRepository
does not require any extra configuration. This is because the AccountDataSourceConfig
define earlier takes care of setting up everything required for the repository to work.
Similarly, define ProductRepository
:
package com.dbvis.demo.repositories.company;
import com.dbvis.demo.entities.company.Product;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProductRepository extends JpaRepository<Product, Long> {}
You can now use the repository to perform operations on the account
and company
databases.
5. Putting It All Together
This is the file structure your project should now have:
ProductController
uses the ProductRepository
autowired object to retrieve data from the company
database, while the UserController
relies on a UserRepository
instance.
Et voilà! Your Spring Boot 3 backend can now retrieve or write data to both the account
and company
databases, respectively.
Exploring Multiple Datasources in a Single Tool With DbVisualizer
If your project grows in complexity and requires multiple database connections, you will need an advanced tool to manage many datasources. This is what DbVisualizer is all about!
DbVisualizer is a complete database client that supports more than 50 different database technologies. This powerful tool enables you to take your database management to the next level. In particular, it comes with advanced data exploration capabilities, in-record data editing support, query optimization functionality, JSON and BLOB data type built-in support, and much more.
What are you waiting for? Try DbVisualizer for free today!
Conclusion
In this tutorial, you learn how to configure Spring Boot 3 to work with several databases. In detail, you saw how to use Spring Boot Data 3 to connect to multiple datasources. As shown here, it is not difficult and only requires some special configuration.
Knowing how to connect to multiple databases in Spring Boot is useful, but without the right data exploration tool everything becomes more complex. DbVisualizer is a MySQL, PostgreSQL, Oracle, and Microsoft SQL Server client that support more than other 50 database technologies. Thanks to its advanced features, managing numerous database connections simultaneously has never been easier. Download DbVisualizer for free!
FAQ
Let’s answer some popular questions on multiple database connections with Spring Boot.
How many databases can you connect to in Spring Boot?
You can connect to as many databases as the backend server can handle. There is no real limit to the number of database connections you can create with Spring Boot. At the same time, keep in mind that each connection to a data source takes resources. So, you should try to limit them to the bare minimum possible.
Can the same Spring Boot app use different database technologies?
Yes, Spring Boot Data supports the connections to several DBMS technologies, including both SQL and NoSQL technologies. You can connect to any database, as long as there is a supported Java JDBC driver.
How many database technologies can you use in a Spring Boot app?
Spring Boot Data does not have limits on the number of database technologies you can connect to. You can have a single DBMS, several connections to it, or a heterogeneous scenario with connections to different database technologies.
Can you simultaneously connect to both SQL and NoSQL databases with Spring Boot Data?
Yes, Spring Boot Data supports both SQL and NoSQL connections. Thus, you can set up both a MySQL and a MongoDB connection. For example, you can configure the Spring Boot application to work with SQL and MongoDB repositories.
Can two datasources have the same name in a Spring Boot app?
Yes, two datasources can have the same name. As long as they are on two different database servers and are configured properly at the application layer, Spring Boot can work with two or more datasources with the same name.
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)