In this blog post, we'll explore the configuration and setup for a Spring Boot 3 application with Java 21 that uses multiple data sources. This setup is useful when dealing with databases of different types, such as MySQL, Oracle, and PostgreSQL.
Technology
- Spring Boot 3.2.0
- Java 21 (Zulu)
- Docker Compose
- Maven
- IntelliJ IDEA 2023.3.1 Community
- Postman
Project Structure
multiple-data-sources-jpa |-- src | |-- main | |-- java | |-- com | |-- henry | |-- configuration | |-- model | |-- repository | |-- service | |-- controller |-- src | |-- test | |-- java | |-- com | |-- henry | |-- ... |-- pom.xml
Application.yaml Configuration
The application file contains configuration deatils for each data source, including URLs, usernames, passowrds, and driver class names.
server:
port: 9000
servlet:
context-path: /
spring:
datasource:
mysql:
url: jdbc:mysql://localhost:3306/test_db?allowPublicKeyRetrieval=true
username: test
password: test_pass
driverClassName: com.mysql.cj.jdbc.Driver
ddlAuto: create-drop
postgres:
url: jdbc:postgresql:postgre_test
username: postgre_test
password: postgre_test
driverClassName: org.postgresql.Driver
ddlAuto: create-drop
oracle:
url: jdbc:oracle:thin:@//localhost:1521/xe
username: system
password: oracle
driverClassName: oracle.jdbc.OracleDriver
ddlAuto: update
Configuration Classes
We've created configuration classes for each data source - MysqlConfig, PostgreConfig, and OracleConfig:
package com.henry.configuration;
import com.henry.record.OracleRecord;
import com.henry.record.PostgreRecord;
import com.henry.record.MysqlRecord;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
@Component
@ConfigurationProperties("spring.datasource")
@Data
public class DataSourceProperties {
private MysqlRecord mysql;
private PostgreRecord postgres;
private OracleRecord oracle;
}
package com.henry.configuration;
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.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 javax.naming.NamingException;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@EnableJpaRepositories(
basePackages = "com.henry.repository.user",
entityManagerFactoryRef = "userEntityManager",
transactionManagerRef = "userTransactionManager"
)
public class MysqlConfig {
@Autowired
private DataSourceProperties dsProperties;
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean userEntityManager()
throws NamingException {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(userDataSource());
em.setPackagesToScan("com.henry.model.user");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(userHibernateProperties());
return em;
}
@Bean
@Primary
public DataSource userDataSource() throws IllegalArgumentException, NamingException {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dsProperties.getMysql().driverClassName());
dataSource.setUrl(dsProperties.getMysql().url());
dataSource.setUsername(dsProperties.getMysql().username());
dataSource.setPassword(dsProperties.getMysql().password());
return dataSource;
}
private Properties userHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.hbm2ddl.auto",dsProperties.getMysql().ddlAuto());
return properties;
}
@Primary
@Bean
public PlatformTransactionManager userTransactionManager() throws NamingException {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(userEntityManager().getObject());
return transactionManager;
}
}
package com.henry.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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 javax.naming.NamingException;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@EnableJpaRepositories(
basePackages = "com.henry.repository.brand",
entityManagerFactoryRef = "brandEntityManager",
transactionManagerRef = "brandTransactionManager"
)
public class OracleConfig {
@Autowired
private DataSourceProperties dsProperties;
@Bean
public LocalContainerEntityManagerFactoryBean brandEntityManager()
throws NamingException {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(brandDataSource());
em.setPackagesToScan("com.henry.model.brand");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(brandHibernateProperties());
return em;
}
@Bean
public DataSource brandDataSource() throws IllegalArgumentException, NamingException {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dsProperties.getOracle().driverClassName());
dataSource.setUrl(dsProperties.getOracle().url());
dataSource.setUsername(dsProperties.getOracle().username());
dataSource.setPassword(dsProperties.getOracle().password());
return dataSource;
}
private Properties brandHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.hbm2ddl.auto", dsProperties.getOracle().ddlAuto());
return properties;
}
@Bean
public PlatformTransactionManager brandTransactionManager() throws NamingException {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(brandEntityManager().getObject());
return transactionManager;
}
}
package com.henry.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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 javax.naming.NamingException;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
@EnableJpaRepositories(
basePackages = "com.henry.repository.company",
entityManagerFactoryRef = "companyEntityManager",
transactionManagerRef = "companyTransactionManager"
)
public class PostgreConfig {
@Autowired
private DataSourceProperties dsProperties;
@Bean
public LocalContainerEntityManagerFactoryBean companyEntityManager()
throws NamingException {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(companyDataSource());
em.setPackagesToScan("com.henry.model.company");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(companyHibernateProperties());
return em;
}
@Bean
public DataSource companyDataSource() throws IllegalArgumentException, NamingException {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dsProperties.getPostgres().driverClassName());
dataSource.setUrl(dsProperties.getPostgres().url());
dataSource.setUsername(dsProperties.getPostgres().username());
dataSource.setPassword(dsProperties.getPostgres().password());
return dataSource;
}
private Properties companyHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.hbm2ddl.auto", dsProperties.getPostgres().ddlAuto());
return properties;
}
@Bean
public PlatformTransactionManager companyTransactionManager() throws NamingException {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(companyEntityManager().getObject());
return transactionManager;
}
}
Record Classes
To encapsulate the configuration properties for each data source, we've defined record classes - MysqlRecord, PostgreRecord, and OracleRecord:
package com.henry.record;
public record MysqlRecord(String url, String username, String password, String driverClassName,String ddlAuto) {
}
package com.henry.record;
public record OracleRecord(String url, String username, String password, String driverClassName,String ddlAuto) {
}
package com.henry.record;
public record PostgreRecord(String url, String username, String password, String driverClassName,String ddlAuto) {
}
Repositories
Repository interfaces extend the CrudRepository for each entity (Brand, Company, User):
package com.henry.repository.brand;
import com.henry.model.brand.Brand;
import org.springframework.data.repository.CrudRepository;
public interface BrandRepository extends CrudRepository<Brand,Long> {
}
package com.henry.repository.company;
import com.henry.model.company.Company;
import org.springframework.data.repository.CrudRepository;
public interface CompanyRepository extends CrudRepository<Company,Long> {
}
package com.henry.repository.user;
import com.henry.model.user.User;
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User,Long> {
}
Services
Service classes (BrandServiceImpl, CompanyServiceImpl, UserServiceImpl) implement a common interface (DefaultService) for generic CRUD operations:
package com.henry.service;
public sealed interface DefaultService<T, G> permits UserServiceImpl, CompanyServiceImpl, BrandServiceImpl {
T save(T obj);
Iterable<T> findAll();
T findById(G id);
}
Services
Service classes (BrandServiceImpl, CompanyServiceImpl, UserServiceImpl) implement a common interface (DefaultService) for generic CRUD operations:
package com.henry.service;
public sealed interface DefaultService<T, G> permits UserServiceImpl, CompanyServiceImpl, BrandServiceImpl {
T save(T obj);
Iterable<T> findAll();
T findById(G id);
}package com.henry.service;
import com.henry.model.brand.Brand;
import com.henry.repository.brand.BrandRepository;
import org.springframework.stereotype.Service;
@Service
public final class BrandServiceImpl implements DefaultService<Brand, Long> {
private final BrandRepository brandRepository;
public BrandServiceImpl(BrandRepository brandRepository) {
this.brandRepository = brandRepository;
}
@Override
public Brand save(Brand obj) {
return brandRepository.save(obj);
}
@Override
public Iterable<Brand> findAll() {
return brandRepository.findAll();
}
@Override
public Brand findById(Long id) {
return brandRepository.findById(id).get();
}
}
package com.henry.service;
import com.henry.model.company.Company;
import com.henry.repository.company.CompanyRepository;
import org.springframework.stereotype.Service;
@Service
public final class CompanyServiceImpl implements DefaultService<Company, Long> {
private final CompanyRepository companyRepository;
public CompanyServiceImpl(CompanyRepository companyRepository) {
this.companyRepository = companyRepository;
}
@Override
public Company save(Company obj) {
return companyRepository.save(obj);
}
@Override
public Iterable<Company> findAll() {
return companyRepository.findAll();
}
@Override
public Company findById(Long id) {
return companyRepository.findById(id).get();
}
}
package com.henry.service;
import com.henry.model.user.User;
import com.henry.repository.user.UserRepository;
import org.springframework.stereotype.Service;
@Service
public final class UserServiceImpl implements DefaultService<User,Long> {
private final UserRepository userRepository;
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public User save(User obj) {
return userRepository.save(obj);
}
@Override
public Iterable<User> findAll() {
return userRepository.findAll();
}
@Override
public User findById(Long id) {
return userRepository.findById(id).get();
}
}
REST Controllers
REST controllers (BrandController, CompanyController, UserController) handle HTTP requests for creating entities:
package com.henry.controller;
import com.henry.model.brand.Brand;
import com.henry.service.DefaultService;
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;
@RestController
@RequestMapping("/api/v3")
public class BrandController {
private final DefaultService<Brand, Long> defaultService;
public BrandController(DefaultService<Brand, Long> defaultService) {
this.defaultService = defaultService;
}
@PostMapping("/brands")
public Brand createEmployee(@RequestBody Brand brand) {
return defaultService.save(brand);
}
}
package com.henry.controller;
import com.henry.model.company.Company;
import com.henry.service.DefaultService;
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;
@RestController
@RequestMapping("/api/v2")
public class CompanyController {
private final DefaultService<Company,Long> defaultService;
public CompanyController(DefaultService<Company, Long> defaultService) {
this.defaultService = defaultService;
}
@PostMapping("/companies")
public Company createEmployee(@RequestBody Company company) {
return defaultService.save(company);
}
}
package com.henry.controller;
import com.henry.model.user.User;
import com.henry.service.DefaultService;
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;
@RestController
@RequestMapping("/api/v1")
public class UserController {
private final DefaultService<User,Long> defaultService;
public UserController(DefaultService<User, Long> defaultService) {
this.defaultService = defaultService;
}
@PostMapping("/users")
public User createEmployee(@RequestBody User user) {
return defaultService.save(user);
}
}
Test Classes
JUnit test classes (BrandServiceTest, CompanyServiceTest, UserServiceTest) use Mockito for mocking dependencies:
package com.henry;
import com.google.common.collect.Iterables;
import com.henry.model.brand.Brand;
import com.henry.repository.brand.BrandRepository;
import com.henry.service.BrandServiceImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class BrandServiceTest {
@Mock
private BrandRepository brandRepository;
@InjectMocks
private BrandServiceImpl brandService;
@Test
void testSaveBrand() {
Brand brand = Brand.builder()
.id(1L)
.name("Test Brand")
.build();
when(brandRepository.save(any())).thenReturn(brand);
Brand saved = brandService.save(brand);
assertEquals(brand, saved);
verify(brandRepository).save(any());
}
@Test
void testFindAllBrands() {
Brand brand1 = Brand.builder()
.id(1L)
.name("Test Brand")
.build();
Brand brand2 = Brand.builder()
.id(2L)
.name("Demo Brand")
.build();
when(brandRepository.findAll()).thenReturn(Arrays.asList(brand1, brand2));
Iterable<Brand> result = brandService.findAll();
assertEquals(2, Iterables.size(result));
verify(brandRepository).findAll();
}
@Test
void testFindBrandById() {
Brand brand = Brand.builder()
.id(1L)
.name("Demo Brand")
.build();
when(brandRepository.findById(1L)).thenReturn(Optional.of(brand));
Brand result = brandService.findById(1L);
assertEquals(brand, result);
verify(brandRepository).findById(1L);
}
}package com.henry;
import com.google.common.collect.Iterables;
import com.henry.model.company.Company;
import com.henry.repository.company.CompanyRepository;
import com.henry.service.CompanyServiceImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
class CompanyServiceTest {
@Mock
private CompanyRepository companyRepository;
@InjectMocks
private CompanyServiceImpl companyService;
@Test
void testSaveCompany() {
Company company =
Company.builder()
.id(1L)
.name("Test Corp")
.build();
when(companyRepository.save(any())).thenReturn(company);
Company saved = companyService.save(company);
assertEquals(company, saved);
verify(companyRepository).save(any());
}
@Test
void testFindAllCompanies() {
Company comp1 = Company.builder()
.id(1L)
.name("Test Corp")
.build();
Company comp2 = Company.builder()
.id(2L)
.name("Demo Corp")
.build();
when(companyRepository.findAll()).thenReturn(Arrays.asList(comp1, comp2));
Iterable<Company> result = companyService.findAll();
assertEquals(2, Iterables.size(result));
verify(companyRepository).findAll();
}
@Test
void testFindCompanyById() {
Company company = Company.builder()
.id(1L)
.name("Test Corp")
.build();
when(companyRepository.findById(1L)).thenReturn(Optional.of(company));
Company result = companyService.findById(1L);
assertEquals(company, result);
verify(companyRepository).findById(1L);
}
}package com.henry;
import com.google.common.collect.Iterables;
import com.henry.model.user.User;
import com.henry.repository.user.UserRepository;
import com.henry.service.UserServiceImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserServiceImpl userService;
@Test
public void saveUser_shouldPersistUser() {
/**
int x = 10;
int y = 20;
String result = STR."\{x} + \{y} = \{x + y}";
string templates are a preview feature and are disabled by default.
Are string templates supported yet? - IntelliJ support - JetBrains
https://intellij-support.jetbrains.com/hc/en-us/community/posts/13451540436114-Are-string-templates-supported-yet-
**/
// Create a User
User user = User.builder()
.id(1L)
.name("John")
.lastName("Doe")
.build();
when(userRepository.save(any())).thenReturn(user);
User saved = userService.save(user);
assertEquals(user, saved);
verify(userRepository).save(any());
}
@Test
void testFindAllUsers() {
User user1 = User.builder()
.id(1L)
.name("John")
.lastName("Doe")
.build();
User user2 = User.builder()
.id(2L)
.name("John")
.lastName("Doe")
.build();
when(userRepository.findAll()).thenReturn(Arrays.asList(user1, user2));
Iterable<User> result = userService.findAll();
assertEquals(2, Iterables.size(result));
verify(userRepository).findAll();
}
@Test
void testFindUserById() {
User user = User.builder()
.id(1L)
.name("John")
.lastName("Doe")
.build();
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
User result = userService.findById(1L);
assertEquals(user, result);
verify(userRepository).findById(1L);
}
}Maven Configuration
The pom.xml file manages project dependencies and build configuration:
<?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.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.henry</groupId>
<artifactId>multiple-data-sources-jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>multiple-data-sources-jpa</name>
<description>Demo project multiple data sources jpa</description>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!-- Exclude the Tomcat dependency -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Use Jetty instead -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MARIADB Connector -->
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
</dependency>
<!-- Mysql Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<!-- ORACLE database driver -->
<!-- https://mvnrepository.com/artifact/oracle/ojdbc6 -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
</dependency>
<!-- POSTGRESQL database driver -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.antlr/stringtemplate
<dependency>
<groupId>org.antlr</groupId>
<artifactId>stringtemplate</artifactId>
<version>4.0.2</version>
</dependency>
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
</project>
Environment Setup with Docker Compose
To simplify the setup of your application's environment, you can use Docker Compose. Below is a docker-compose-multiple-db.yml file that defines services for Oracle, PostgreSQL, and MySQL databases:
version: '3'
services:
oracle:
image: pengbai/docker-oracle-xe-11g-r2
ports:
- "1521:1521"
- "8080:8080"
shm_size: 1g
postgres:
image: postgres:14.1
container_name: postgre_test
environment:
POSTGRES_USER: postgre_test
POSTGRES_PASSWORD: postgre_test
POSTGRES_DB: postgre_test
ports:
- "5432:5432"
mysql:
image: mysql/mysql-server:latest
container_name: mysql-docker-container
environment:
MYSQL_ROOT_PASSWORD: mypass
MYSQL_DATABASE: test_db
MYSQL_USER: test
MYSQL_PASSWORD: test_pass
ports:
- "3306:3306"
Run command:
docker-compose -f docker-compose-multiple-db.yml up -d
Only for oracle:
mvn install:install-file "-Dfile=path/to/your/ojdbc6.jar" "-DgroupId=com.oracle" "-DartifactId=ojdbc6" "-Dversion=11.2.0.4" "-Dpackaging=jar" "-DgeneratePom=true"
Run & Test
Run Spring Boot application with command: by console, IntelliJ etc.
mvn test -Dtest=UserServiceTest
mvn test -Dtest=BrandServiceTest
mvn test -Dtest=CompanyServiceTest
Run locally: mvn spring-boot:run
POST
http://localhost:9000/api/v1/users
POST
http://localhost:9000/api/v2/companies
POST
http://localhost:9000/api/v3/brands
.png)
No comments:
Post a Comment