Steps to Configure Multiple Datasourse in Spring Boot Application

Below are the steps to configure multiple Datasource in the Spring Boot application.

Step 1: First, we need to configure the Properties file.

application.properties:

# DataSource configuration
#DB1
spring.datasource.url=jdbc:mysql://localhost:8084/db1
spring.datasource.username=root
spring.datasource.password=tisha
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#DB2
second.datasource.url=jdbc:mysql://localhost:8084/db2
second.datasource.username=root
second.datasource.password=tisha
second.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA (Java Persistence API) configuration
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
# create,update,delete
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Step 2: Now, we will configure Dependency in pom.xml file.

XML
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>org.techous</groupId>
    <artifactId>Trigger-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Trigger-demo</name>
    <description>master slave project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Project Structure:

Below we can see the Project structure after designing multiple datasources.


First, we made database 1 configuration according to above image.

Db1Config.java:

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

// Configuration class for configuring the second database
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "secondEntityMangerFactoryBean",
        basePackages = {"org.techous.triggerdemo.db2.repository"},
        transactionManagerRef = "secondTransactionManager"
)
public class Db2Config {

    @Autowired
    private Environment environment;

    // Configuring the data source for the second database
    @Bean(name = "secondDataSource")
    @Primary
    public DataSource dataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(environment.getProperty("second.datasource.url"));
        dataSource.setDriverClassName(environment.getProperty("second.datasource.driver-class-name"));
        dataSource.setUsername(environment.getProperty("second.datasource.username"));
        dataSource.setPassword(environment.getProperty("second.datasource.password"));

        return dataSource;
    }

    // Configuring the entity manager factory for the second database
    @Primary
    @Bean(name = "secondEntityMangerFactoryBean")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(dataSource());
        bean.setPackagesToScan("org.techous.triggerdemo.db2.model");

        JpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        bean.setJpaVendorAdapter(adapter);

        Map<String,String> props = new HashMap<>();
        props.put("hibernate.dialect","org.hibernate.dialect.MySQLDialect");
        props.put("hibernate.show_sql","true");
        props.put("hibernate.hbm2ddl.auto","update");
        bean.setJpaPropertyMap(props);

        return bean;
    }

    // Configuring the platform transaction manager for the second database
    @Bean(name = "secondTransactionManager")
    @Primary
    public PlatformTransactionManager transactionManager(){
        JpaTransactionManager manager = new JpaTransactionManager();
        manager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
        return manager;
    }
}


In above code, we are doing add configuration for calling db1. We are using @configuration annotation in this class and the class become a bean. Here we use Environment class for configure internal environment then use Datasourse for making different database configuration. Then use LocalContinerEntityManager to set what package scan and run first whatever path we have provided this considered database and store all data there. This configuration is used only for making multiple datasourse here. Rest of things as it is like simple crud operation we are done.

ProductController.java:

Java
package org.techous.triggerdemo.db1.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.techous.triggerdemo.db1.model.Product;
import org.techous.triggerdemo.db1.service.ProductService;

// Controller class for handling product-related requests
@RestController
@RequestMapping("/product")
public class ProductController {

    @Autowired
    private ProductService productService;

    // Endpoint for saving a product
    @PostMapping("saveProduct")
    public ResponseEntity<Product> saveProduct(@RequestBody Product product){
        Product myproduct = productService.saveProduct(product);
        return new ResponseEntity<>(myproduct, HttpStatus.OK);
    }

}

The above class is service class endpoint for calling APIs.

ProductService.java:

Java
package org.techous.triggerdemo.db1.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.techous.triggerdemo.db1.model.Product;
import org.techous.triggerdemo.db1.repository.ProductRepo;

// Service class for product-related operations
@Service
public class ProductService {

    @Autowired
    private ProductRepo productRepo;

    // Method to save a product
    public Product saveProduct(Product product) {
        return productRepo.save(product);
    }
}

The above class is productService class for making all business logic here.

Product.java:

Java
package org.techous.triggerdemo.db1.model;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

// Entity class for Product
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "product")
public class Product {

    @Id
    private int productId;
    private String name;
    private int price;
}

The above class is our entity class.

ProductRepo.java:

Java
package org.techous.triggerdemo.db1.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.techous.triggerdemo.db1.model.Product;

// Repository interface for Product
@Repository
public interface ProductRepo extends JpaRepository<Product,Integer> {

}


This above class is our repository to save anythings.

This is the Configuration of database 1 (db1).

Now, we will do another database (db2) configuration below.

Db2Config2.java:

Java
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "secondEntityMangerFactoryBean",
        basePackages = {"org.techous.triggerdemo.db2.repository"},
        transactionManagerRef = "secondTransactionManager"
)
public class Db2Config {

    @Autowired
    private Environment environment;

    // Configuring the datasource
    @Bean(name = "secondDataSource")
    @Primary
    public DataSource dataSource(){
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(environment.getProperty("second.datasource.url"));
        dataSource.setDriverClassName(environment.getProperty("second.datasource.driver-class-name"));
        dataSource.setUsername(environment.getProperty("second.datasource.username"));
        dataSource.setPassword(environment.getProperty("second.datasource.password"));

        return dataSource;
    }

    // Configuring the entity manager factory
    @Primary
    @Bean(name = "secondEntityMangerFactoryBean")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(dataSource());
        bean.setPackagesToScan("org.techous.triggerdemo.db2.model");

        JpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        bean.setJpaVendorAdapter(adapter);

        Map<String,String> props = new HashMap<>();
        props.put("hibernate.dialect","org.hibernate.dialect.MySQLDialect");
        props.put("hibernate.show_sql","true");
        props.put("hibernate.hbm2ddl.auto","update");
        bean.setJpaPropertyMap(props);

        return bean;
    }

    // Configuring the platform transaction manager
    @Bean(name = "secondTransactionManager")
    @Primary
    public PlatformTransactionManager transactionManager(){
        JpaTransactionManager manager = new JpaTransactionManager();
        manager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
        return manager;
    }
}

As per saying above, same configuration made here also and define properties path as per our database design. (only change in package URL)

UserController.java:

Java
package org.techous.triggerdemo.db2.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.techous.triggerdemo.db2.model.User;
import org.techous.triggerdemo.db2.service.UserService;

@RestController
@RequestMapping("/api")
public class UserController {

    @Autowired
    private UserService userService;

    // Endpoint to save a user
    @PostMapping("/saveUser")
    public ResponseEntity<User> save(@RequestBody User user){
        User myuser = userService.saveUser(user);
        return new ResponseEntity<>(myuser, HttpStatus.OK);
    }

}


UserService.java:

Java
package org.techous.triggerdemo.db2.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.techous.triggerdemo.db2.model.User;
import org.techous.triggerdemo.db2.repository.UserRepository;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    // Service method to save a user
    public User saveUser(User user) {
        return userRepository.save(user);
    }
}

User.java:

Java
package org.techous.triggerdemo.db2.model;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int userId; // Unique identifier for the user

    private String name; // Name of the user

    private int age; // Age of the user
}

UserRepository.java:

Java
package org.techous.triggerdemo.db2.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.techous.triggerdemo.db2.model.User;

@Repository
public interface UserRepository extends JpaRepository<User,Integer> {
}

We have completed all our database configuration.

Now, when we insert user, it will save in db2 database and when we save product, it will save in db1.


Output:

First, we will add User.

In the below screen, we can see the user added to the database.

Now, we will add Product.

Now, we can see the product added to the database.

This way we can Configure Multiple DataSource in a single Spring Boot application.



Configure Multiple Datasource in Spring Boot Application

Sometimes we build some applications that need multiple databases. Our data is arranged to store multiple databases, like one database designed for another need or another database for another need. So, in this article, we will see how to configure multiple in the Spring Boot application.

Note: We are using MySQL 8 workbench for both the database.

Similar Reads

Steps to Configure Multiple Datasourse in Spring Boot Application

Below are the steps to configure multiple Datasource in the Spring Boot application....

Contact Us