Spring Boot
Data Sources
Database Configuration
Multi-DataSource
Java Programming

Spring Boot configure and use two data sources

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Spring Boot simplifies the development of Spring applications, particularly with regard to configuration. In scenarios where an application requires interaction with multiple databases, Spring Boot offers a straightforward approach to configure and use multiple data sources. This can be particularly useful for larger systems that need to handle different types of data separately or when integrating with legacy systems that utilize different databases.

Understanding Spring Boot Data Source Configuration

Spring Boot utilizes Spring Data to simplify database interaction. Typically, configuring a data source in Spring Boot involves setting properties in the application.properties or application.yml file. By default, if you add a Spring Data JPA dependency to your project, Spring Boot auto-configures a single data source. However, configuring multiple data sources requires a bit more setup.

Structuring the Application for Multiple Data Sources

To set up multiple data sources, you’ll typically create additional configuration classes—each specifying a DataSource, EntityManagerFactory, and TransactionManager. Here's a general step-by-step guide on how to do this:

  1. Define Database Properties: Define each database's connection properties in application.properties.
  2. Configure Data Source Beans: Create configuration beans for each data source.
  3. Configure Entity Manager Factories: Each data source will need its EntityManager configured.
  4. Configure Transaction Managers: Separate transaction managers might be necessary if transactions are specific to database operations.
  5. Use the Data Sources: Use the configured data sources in your repository classes.

Example: Configuring Two Data Sources

Below is an example demonstrating the configuration of two separate data sources using Spring Boot.

First, let’s define the properties for both data sources in application.properties:

properties
1# Primary database
2spring.datasource1.url=jdbc:mysql://localhost:3306/userdb
3spring.datasource1.username=root
4spring.datasource1.password=root
5spring.datasource1.driver-class-name=com.mysql.jdbc.Driver
6
7# Secondary database
8spring.datasource2.url=jdbc:mysql://localhost:3306/productdb
9spring.datasource2.username=root
10spring.datasource2.password=root
11spring.datasource2.driver-class-name=com.mysql.jdbc.Driver

Next, create a configuration class for each data source:

java
1@Configuration
2@EnableTransactionManagement
3@EnableJpaRepositories(
4    basePackages = "com.example.demo.repository.user",
5    entityManagerFactoryRef = "userEntityManagerFactory",
6    transactionManagerRef = "userTransactionManager"
7)
8public class UserDbConfig {
9
10    @Bean(name = "userDataSource")
11    @ConfigurationProperties(prefix = "spring.datasource1")
12    public DataSource dataSource() {
13        return DataSourceBuilder.create().build();
14    }
15
16    @Bean(name = "userEntityManagerFactory")
17    public LocalContainerEntityManagerFactoryBean 
18    entityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("userDataSource") DataSource dataSource) {
19        return builder
20                .dataSource(dataSource)
21                .packages("com.example.demo.domain.user")
22                .persistenceUnit("user")
23                .build();
24    }
25
26    @Bean(name = "userTransactionManager")
27    public PlatformTransactionManager transactionManager(@Qualifier("userEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
28        return new JpaTransactionManager(entityManagerFactory);
29    }
30}
31
32@Configuration
33@EnableTransactionManagement
34@EnableJpaRepositories(
35    basePackages = "com.example.demo.repository.product",
36    entityManagerFactoryRef = "productEntityManagerFactory",
37    transactionManagerRef = "productTransactionManager"
38)
39public class ProductDbConfig {
40
41    @Bean(name = "productDataSource")
42    @ConfigurationProperties(prefix = "spring.datasource2")
43    public DataSource dataSource() {
44        return DataSourceBuilder.create().build();
45    }
46
47    @Bean(name = "productEntityManagerFactory")
48    public LocalContainerEntityManagerFactoryBean 
49    entityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("productDataSource") DataSource dataSource) {
50        return builder
51                .dataSource(dataSource)
52                .packages("com.example.demo.domain.product")
53                .persistenceUnit("product")
54                .build();
55    }
56
57    @Bean(name = "productTransactionManager")
58    public PlatformTransactionManager transactionManager(@Qualifier("productEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
59        return new JpaTransactionManager(entityManagerFactory);
60    }
61}

Key Points Table

Key PointDescription
Multiple Configuration ClassesSeparate configuration classes for each data source.
@EnableJpaRepositories AnnotationSpecifies the repository location, EntityManager, and TransactionManager for each data unit.
DataSource ConfigurationDefined via application properties and configured beans.
Separate EntityManagers and Transaction ManagersEnsures that each data source operates independently with its transaction management.

Conclusion

Configuring multiple data sources in Spring Boot, although somewhat intricate, can greatly enhance the flexibility and scalability of your application. By isolating database operations, you can maximize performance and maintain a clean separation of concerns within your application architecture.

This setup may seem complex at first, but it becomes quite manageable as you familiarize yourself with the key components: DataSource, EntityManager, and TransactionManager configurations. Using these configurations, engineers can effectively connect their Spring applications to multiple databases, empowering robust data management and operations.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.