Spring Boot

Configure Multiple Databases Spring JPA Spring Boot

Overview

In this article, we will explore a simple Spring Boot application to implement a simple Spring configuration for a Spring Data JPA with multiple databases requirements.

Create an application to store information related to Books in a database named book-database.

In the same application, we want to store information related to Author in a separate database named author-database.

Now, create the entities for both domains:

Entities classes

First, let’s create a simple entity class for the Book domain.

Here is the first Book entity:

package com.dineshonjava.myapp.model.book;

@Entity
@Table(schema = "books")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int bookId;

    private String title;

    private String author;

    private String publisher;

    private double price;
}

Now, let’s create a simple entity class for the Author domain.

package com.dineshonjava.myapp.model.author;

@Entity
@Table(schema = "authors")
public class Author {

    @Id
    private int authorId;

    private String name;

    private String email;
}

As you can see both entity classes, we have placed them in independent packages.

Let’s create JPA repositories for both entity classes.

The JPA Repositories

Let’s create a JPA repository class for the Book entity, BookRepository:

package com.dineshonjava.myapp.dao.book;

public interface BookRepository
  extends JpaRepository<Book, Integer> { }

Next, let’s create another repository class for Author, AuthorRepository:

package com.dineshonjava.myapp.dao.author;

public interface AuthorRepository
  extends JpaRepository<Author, Integer> { }

Again we have placed both repositories into different packages due to separate databases.

Let’s move to create configurations for both databases using Spring Boot. We can simply add this DB configuration into an application.properties file.

By default, Spring Boot will instantiate its default DataSource with the configuration properties prefixed by spring.datasource.* but we can create separate prefixed values as well.

Database configurations

Let’s add the following database configuration for the book database into the application.properties file.

spring.datasource.jdbcUrl = <<book-database-url>>
spring.datasource.username = <<book-database-username>>
spring.datasource.password = <<book-database-passwaord>>

Let’s the follow configuration related to the second database using the same way to configure the second DataSource as below:

spring.author-datasource.jdbcUrl = <<author-database-url>>
spring.author-datasource.username = <<author-database-username>>
spring.author-datasource.password = <<author-database-passwaord>>

Now, we need to create different Spring Boot autoconfiguration files to pick up both database configurations from the properties file as added above for two different DataSources.

Spring Boot autoconfiguration

Let’s create Spring Boot autoconfiguration for the book database.

@Configuration
@EnableJpaRepositories(
  basePackages = "com.dineshonjava.myapp.dao.book",
  entityManagerFactoryRef = "bookEntityManager",
  transactionManagerRef = "bookTransactionManager")
public class PersistenceBookAutoConfiguration {
    
    @Primary
    @Bean
    @ConfigurationProperties(prefix="spring.datasource")
    public DataSource bookDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean bookEntityManager() {
        LocalContainerEntityManagerFactoryBean em
                = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(bookDataSource());
        em.setPackagesToScan(
                new String[] { "com.dineshonjava.myapp.model.books"});

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        Map<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto",
                env.getProperty("hibernate.hbm2ddl.auto"));
        properties.put("hibernate.dialect",
                env.getProperty("hibernate.dialect"));
        em.setJpaPropertyMap(properties);

        return em;
    }
    @Bean
    @Primary
    public PlatformTransactionManager bookTransactionManager() {

        JpaTransactionManager transactionManager
                = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(
                entityManager().getObject());
        return transactionManager;
    }
}

Next, let’s create Spring Boot autoconfiguration for the author database.

@Configuration
@EnableJpaRepositories(
  basePackages = "com.dineshonjava.myapp.dao.author", 
  entityManagerFactoryRef = "authorEntityManager", 
  transactionManagerRef = "authorTransactionManager")
public class PersistenceAuthorAutoConfiguration {
   
    @Bean
    @ConfigurationProperties(prefix="spring.author-datasource")
    public DataSource authorDataSource() {
        return DataSourceBuilder.create().build();
    }
   
    @Bean
    public LocalContainerEntityManagerFactoryBean authorEntityManager() {
        LocalContainerEntityManagerFactoryBean em
                = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(bookDataSource());
        em.setPackagesToScan(
                new String[] { "com.dineshonjava.myapp.model.authors"});

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        Map<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto",
                env.getProperty("hibernate.hbm2ddl.auto"));
        properties.put("hibernate.dialect",
                env.getProperty("hibernate.dialect"));
        em.setJpaPropertyMap(properties);

        return em;
    }

    @Bean
    public PlatformTransactionManager authorTransactionManager() {

        JpaTransactionManager transactionManager
                = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(
                entityManager().getObject());
        return transactionManager;
    }
}

Now we have defined the data source properties inside the application.properties according to the Boot autoconfiguration convention.

You can see the above configuration files. These are annotating the data source bean creation method with @ConfigurationProperties and we have used the corresponding config prefix.

DataSourceBuilder of Spring Boot takes care automatically how to create DataSource for each database using defined configurations.

Summary

We have looked at a practical overview of how we can configure multiple databases into a Spring Boot application.

Previous
Next
Dinesh Rajput

Dinesh Rajput is the chief editor of a website Dineshonjava, a technical blog dedicated to the Spring and Java technologies. It has a series of articles related to Java technologies. Dinesh has been a Spring enthusiast since 2008 and is a Pivotal Certified Spring Professional, an author of a book Spring 5 Design Pattern, and a blogger. He has more than 10 years of experience with different aspects of Spring and Java design and development. His core expertise lies in the latest version of Spring Framework, Spring Boot, Spring Security, creating REST APIs, Microservice Architecture, Reactive Pattern, Spring AOP, Design Patterns, Struts, Hibernate, Web Services, Spring Batch, Cassandra, MongoDB, and Web Application Design and Architecture. He is currently working as a technology manager at a leading product and web development company. He worked as a developer and tech lead at the Bennett, Coleman & Co. Ltd and was the first developer in his previous company, Paytm. Dinesh is passionate about the latest Java technologies and loves to write technical blogs related to it. He is a very active member of the Java and Spring community on different forums. When it comes to the Spring Framework and Java, Dinesh tops the list!

Share
Published by
Dinesh Rajput

Recent Posts

Strategy Design Patterns using Lambda

Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…

2 years ago

Decorator Pattern using Lambda

Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…

2 years ago

Delegating pattern using lambda

Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…

2 years ago

Spring Vs Django- Know The Difference Between The Two

Technology has emerged a lot in the last decade, and now we have artificial intelligence;…

2 years ago

TOP 20 MongoDB INTERVIEW QUESTIONS 2022

Managing a database is becoming increasingly complex now due to the vast amount of data…

2 years ago

Scheduler @Scheduled Annotation Spring Boot

Overview In this article, we will explore Spring Scheduler how we could use it by…

2 years ago