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:
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.
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.
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.
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.
We have looked at a practical overview of how we can configure multiple databases into a Spring Boot application.
Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…
Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…
Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…
Technology has emerged a lot in the last decade, and now we have artificial intelligence;…
Managing a database is becoming increasingly complex now due to the vast amount of data…
Overview In this article, we will explore Spring Scheduler how we could use it by…