[PART 2] Spring Boot - Multiple datasource (database) with JDBC and JPA
We start with postgreSQL because this our primary database connection and we do all CRUD stuff from here. We need 2 class, which use for connection and configuration of datasource.
DatasourceConfigurationPostgreSQL
package com.robbi.demo.config.postgresql;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.robbi.demo.utils.LoggerFactoryUtil;
@Configuration
public class DatasourceConfigurationPostgreSQL {
private static final Logger LOG = LoggerFactoryUtil.getLogger();
@Bean
@ConfigurationProperties("spring.datasource.postgresql")
public DataSourceProperties dataSourcePropertiesPostgreSQL() {
LOG.info("spring.datasource.postgresql");
return new DataSourceProperties();
}
@Bean
@Primary
public DataSource dataSourcePostgreSQL() {
LOG.info("Initializing PostgreSQL DataSource: {}", dataSourcePropertiesPostgreSQL().getUrl());
return dataSourcePropertiesPostgreSQL()
.initializeDataSourceBuilder()
.build();
}
}Take note on anotation @ConfigurationProperties and @Primary that I applied here.
With @ConfigurationProperties("spring.datasource.postgresql"), this tells Spring to bind configuration properties starting with spring.datasource.postgresql to this bean. This @Primary is to tells Spring that if multiple DataSource beans exist, this one should be preferred for injection.
Overall, this code defines two beans :
dataSourcePropertiesPostgreSQL- Holds the configuration properties for the PostgreSQL database connection, retrieved from the application.properties file.dataSourcePostgreSQL- The actual DataSource object used for connecting to the PostgreSQL database.
DataSourceJPAConfigPostgreSQL
package com.robbi.demo.config.postgresql;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
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 com.robbi.demo.utils.LoggerFactoryUtil;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.robbi.demo.source.postgresql.repo",
entityManagerFactoryRef = "postgresqlEntityManagerFactory",
transactionManagerRef = "postgresqlTransactionManager"
)
public class DataSourceJPAConfigPostgreSQL {
private static final Logger LOG = LoggerFactoryUtil.getLogger();
@Value("${spring.jpa.postgresql.hibernate.ddl-auto}")
private String hibernateDdlAuto;
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean postgresqlEntityManagerFactory(
@Qualifier("dataSourcePostgreSQL") DataSource dataSource,
EntityManagerFactoryBuilder builder) {
LOG.info("postgresqlEntityManagerFactory with dataSourcePostgreSQL : {}",dataSource);
// Configure properties for Hibernate, including DDL auto-generation
Map<String, String> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", hibernateDdlAuto); // Or "update", "create-drop" based on your requirement
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
return builder
.dataSource(dataSource)
.packages("com.robbi.demo.source.postgresql.model")
.persistenceUnit("postgresql") // Added this line for clarity
.properties(properties) // Add the Hibernate properties here
.build();
}
@Bean
public PlatformTransactionManager postgresqlTransactionManager(
@Qualifier("postgresqlEntityManagerFactory") LocalContainerEntityManagerFactoryBean postgresqlEntityManagerFactory) {
LOG.info("postgresqlTransactionManager with postgresqlEntityManagerFactory : {}",postgresqlEntityManagerFactory);
return new JpaTransactionManager(Objects.requireNonNull(postgresqlEntityManagerFactory.getObject()));
}
}This code configures JPA (Java Persistence API) for the PostgreSQL datasource defined earlier.
The class is named DataSourceJPAConfigPostgreSQL. This aligns with its purpose: configuring JPA for the PostgreSQL datasource.
It has three annotations:
@Configuration: Marks it as a Spring configuration class.@EnableTransactionManagement: Enables transaction management for the application.@EnableJpaRepositories: Enables JPA repositories for a specific base package (com.robbi.demo.source.postgresql.repo). It also specifies references to the custom-namedEntityManagerFactoryandTransactionManagerbeans.
Hibernate DDL Auto-generation:
- This
@Value("${spring.jpa.postgresql.hibernate.ddl-auto}")injects the value of thespring.jpa.postgresql.hibernate.ddl-autoproperty from theapplication.properties file. This property controls how Hibernate creates or updates database tables based on our entity classes
Method postgresqlEntityManagerFactory() :
- Uses
@Beanto declare a bean of typeLocalContainerEntityManagerFactoryBean. This bean factory builds the JPAEntityManagerFactoryused for interacting with the database. - I mark and annotates it with
@Primary. This indicates it should be preferred if multipleEntityManagerFactorybeans exist. - Takes two arguments:
@Qualifier("dataSourcePostgreSQL") DataSource dataSource: Injects thedataSourcePostgreSQLbean defined inDatasourceConfigurationPostgreSQL.EntityManagerFactoryBuilder builder: Provides a builder object to configure theEntityManagerFactory.
If you notice, i also create a HashMap named properties to store configuration properties for Hibernate, i currently insert 2 value here :
hibernate.hbm2ddl.auto: This controls how Hibernate creates or updates tables based on your entity classes (βnoneβ, βcreateβ, βcreate-dropβ, or βupdateβ), which i pull from*.propertiesfile.hibernate.dialect: set asorg.hibernate.dialect.PostgreSQLDialect, specifying the dialect to use for interacting with PostgreSQL.
This method return builder to configure the EntityManagerFactory:
- Sets the dataSource property to the injected dataSource bean.
- Sets the packages property to scan for JPA entity classes in the package com.markono.tnf.source.postgresql.model. This is where your entity classes representing database tables reside.
- Sets the persistenceUnit : property to βpostgresqlβ
- Builds and returns the LocalContainerEntityManagerFactoryBean object.
Method postgresqlTransactionManager() :
- Uses
@Beanto declare a bean of typePlatformTransactionManager. This bean manages database transactions. - Takes one argument:
@Qualifier("postgresqlEntityManagerFactory") LocalContainerEntityManagerFactoryBean postgresqlEntityManagerFactory: Injects the postgresqlEntityManagerFactory bean created earlier.
- Creates a new
JpaTransactionManagerobject, passing in the retrievedEntityManagerFactory. This ensures transactions are managed within the context of the configuredEntityManagerFactory. - Returns the
JpaTransactionManagerbean.
The next part of this series will delve into the configuration of the MSSQL database. Stay tuned for Part 3 π
Have some thoughts, discussion or feedback on this post?
βΈ What is webmention? How to send interactions!
webmention with this page.
You can also mention this URL on any website that supports WebMention.
Have you written a response to this post? Let me know the URL:Don't have WebMention? Use Comment Parade!
No webmentions yet.
Comments section coming soon. For now, send a webmention or email.