Product
example.Prerequisites
- JDK 17 or later
- Maven or Gradle
- IDE (IntelliJ IDEA, Eclipse, etc.)
Step 1: Set Up a Spring Boot Project
1.1 Create a New Spring Boot Project
Use Spring Initializr to create a new project with the following dependencies:
- Spring Web
- Spring Data JPA
- H2 Database (for simplicity, but you can use any databases)
Download and unzip the project, then open it in your IDE.
1.2 Configure application.properties
Set up the application properties for your project. This file is located in the src/main/resources
directory. We will define two data sources and their corresponding JPA properties.
# src/main/resources/application.properties
# DataSource 1 (Primary)
spring.datasource.primary.url=jdbc:h2:mem:primarydb
spring.datasource.primary.driverClassName=org.h2.Driver
spring.datasource.primary.username=sa
spring.datasource.primary.password=password
spring.datasource.primary.platform=h2
# DataSource 2 (Secondary)
spring.datasource.secondary.url=jdbc:h2:mem:secondarydb
spring.datasource.secondary.driverClassName=org.h2.Driver
spring.datasource.secondary.username=sa
spring.datasource.secondary.password=password
spring.datasource.secondary.platform=h2
# JPA properties for both data sources
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
Explanation:
- Configures two H2 in-memory databases:
primarydb
andsecondarydb
. - Sets common JPA properties.
Step 2: Define Entity Classes
2.1 Create the Product
Entity for Primary Database
Create an entity class to represent a product in the primary database.
package com.example.demo.primary.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
// Getters and setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
2.2 Create the Product
Entity for Secondary Database
Create an entity class to represent a product in the secondary database.
package com.example.demo.secondary.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private double price;
// Getters and setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
Step 3: Create Repository Interfaces
3.1 Create the ProductRepository
for Primary Database
Create a repository interface for the Product
entity in the primary database.
package com.example.demo.primary.repository;
import com.example.demo.primary.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}
3.2 Create the ProductRepository
for Secondary Database
Create a repository interface for the Product
entity in the secondary database.
package com.example.demo.secondary.repository;
import com.example.demo.secondary.entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}
Step 4: Configure Data Sources and Entity Managers
4.1 Create Configuration for Primary DataSource
Create a configuration class to set up the primary data source and entity manager.
package com.example.demo.config;
import com.example.demo.primary.entity.Product;
import jakarta.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.demo.primary.repository",
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryDataSourceConfig {
@Bean(name = "primaryDataSource")
@Qualifier("primaryDataSource")
public DataSource primaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:h2:mem:primarydb")
.driverClassName("org.h2.Driver")
.username("sa")
.password("password")
.build();
}
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
@Qualifier("primaryDataSource") DataSource primaryDataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(primaryDataSource);
em.setPackagesToScan(Product.class.getPackage().getName());
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryEntityManagerFactory") EntityManagerFactory primaryEntityManagerFactory) {
return new JpaTransactionManager(primaryEntityManagerFactory);
}
}
4.2 Create Configuration for Secondary DataSource
Create a configuration class to set up the secondary data source and entity manager.
package com.example.demo.config;
import com.example.demo.secondary.entity.Product;
import jakarta.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.demo.secondary.repository",
entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@Qualifier("secondaryDataSource")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create()
.url("jdbc:h2:mem:secondarydb")
.driverClassName("org.h2.Driver")
.username("sa")
.password("password")
.build();
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(
@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(secondaryDataSource);
em.setPackagesToScan(Product.class.getPackage().getName());
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory secondaryEntityManagerFactory) {
return new JpaTransactionManager(secondaryEntityManagerFactory);
}
}
Step 5: Create Service and Controller Layers
5.1 Create the ProductService
Create a service class to handle business logic related to products for both databases.
package com.example.demo.service;
import com.example.demo.primary.entity.Product as PrimaryProduct;
import com.example.demo.primary.repository.ProductRepository as PrimaryProductRepository;
import com.example.demo.secondary.entity.Product as SecondaryProduct;
import com.example.demo.secondary.repository.ProductRepository as SecondaryProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProductService {
@Autowired
private PrimaryProductRepository primaryProductRepository;
@Autowired
private SecondaryProductRepository secondaryProductRepository;
public List<PrimaryProduct> getAllPrimaryProducts() {
return primaryProductRepository.findAll();
}
public List<SecondaryProduct> getAllSecondaryProducts
() {
return secondaryProductRepository.findAll();
}
public PrimaryProduct createPrimaryProduct(PrimaryProduct product) {
return primaryProductRepository.save(product);
}
public SecondaryProduct createSecondaryProduct(SecondaryProduct product) {
return secondaryProductRepository.save(product);
}
}
5.2 Create the ProductController
Create a REST controller to expose endpoints for interacting with products in both databases.
package com.example.demo.controller;
import com.example.demo.primary.entity.Product as PrimaryProduct;
import com.example.demo.secondary.entity.Product as SecondaryProduct;
import com.example.demo.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/products")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/primary")
public List<PrimaryProduct> getAllPrimaryProducts() {
return productService.getAllPrimaryProducts();
}
@GetMapping("/secondary")
public List<SecondaryProduct> getAllSecondaryProducts() {
return productService.getAllSecondaryProducts();
}
@PostMapping("/primary")
public PrimaryProduct createPrimaryProduct(@RequestBody PrimaryProduct product) {
return productService.createPrimaryProduct(product);
}
@PostMapping("/secondary")
public SecondaryProduct createSecondaryProduct(@RequestBody SecondaryProduct product) {
return productService.createSecondaryProduct(product);
}
}
Step 6: Running and Testing the Application
6.1 Run the Application
Run the Spring Boot application using your IDE or the command line:
./mvnw spring-boot:run
6.2 Test the Endpoints
Use a tool like Postman or your browser to test the endpoints.
Create a Product in the Primary Database
- URL:
http://localhost:8080/products/primary
- Method: POST
- Body:
{ "name": "Primary Product", "price": 100.0 }
Create a Product in the Secondary Database
- URL:
http://localhost:8080/products/secondary
- Method: POST
- Body:
{ "name": "Secondary Product", "price": 200.0 }
Get All Products from the Primary Database
- URL:
http://localhost:8080/products/primary
- Method: GET
Get All Products from the Secondary Database
- URL:
http://localhost:8080/products/secondary
- Method: GET
Conclusion
In this tutorial, you have learned how to configure and use multiple databases in a Spring Boot 3.2 application with Spring Data JPA. We covered:
- Setting up a Spring Boot project with multiple data sources.
- Defining entity classes and repositories for each database.
- Configuring data sources and entity managers.
- Creating service and controller layers.
- Running and testing the application using REST endpoints.
By following these steps, you can effectively manage and interact with multiple databases in your Spring Boot applications using Spring Data JPA.
Comments
Post a Comment