spring boot multiple database

seanical·2022년 4월 12일

현업에서는 여러가지의 데이터베이스를 연결해야하는일이 굉장히 많다.
Properties를 통한 두개 이상의 데이터베이스를 연결하려면 어떻게 해야할까?

mysql, h2 database를 사용하여 Member객체를 insert 하는 예제를 들어보겠습니다.

  1. Build.gradle 설정

build.gradle 코드

plugins {
	id 'org.springframework.boot' version '2.6.6'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'mysql:mysql-connector-java'
	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'com.h2database:h2'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

사실 다른것은 중요한게 아니고 h2, mysql 을 사용하려면 dependencies에 있는것들을 추가해주면 된다.

  1. application.yaml 추가
    java/resources 폴더 아래application.yaml을 생성하고 다음 아래의 값들을 채워준다.

application.yaml 코드

spring:
  profiles:
    active: dev
---
spring:
  datasource:
    jdbc-url: jdbc:h2:tcp://localhost/~/test
    driver-class-name: org.h2.Driver
    username: sa
    password:

  datasource-mysql:
    jdbc-url:  jdbc:mysql://localhost:3306/streaming?serverTimezone=UTC&characterEncoding=UTF-8
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 1234

  config:
    activate:
      on-profile: "dev"

현업에서는 dev, sandbox, prod, local 같은 Profile을 나눠 환경설정을 하기때문에 다음과 같이 나타내었고 dev 환경에서 datasource를 어떻게 쓰겠다 정의한것이다.

  1. DataSourceConfig 생성

DataSourceConfing 코드

package hello.springboot.config;

import com.zaxxer.hikari.HikariDataSource;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;


@Configuration
public class DataSourceConfig {

    @Profile("dev")
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public HikariDataSource h2dataSource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    @Profile("dev")
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource-mysql")
    public HikariDataSource mySqldataSource(){
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

}

내가 원하는 데이터소스를 정의를 합니다.
HikariDatasource는 데이터베이스를 의미하는게 아니라 h2, mysqlconnection을 도와주는 것이라고 생각하면된다.

  • @Profile("dev")
    위에서 작성한 어떠한 환경(dev)일때 돌아가는지 @Profile("dev")로 표시한것이다.
    현재 환경은 dev라고 application.yaml에 아래와같이 정의하여 현재 dev환경에서 아래 Bean등록을 시도할것이다.
spring:
  profiles:
    active: dev
  • @Bean
    스프링 컨테이너 Bean저장소에 Bean으로 등록할것이다라는 예약어

  • @ConfigurationProperties(prefix = "spring.datasource")

    @ConfigurationProperties(prefix = "spring.datasource")의 의미는
    application.yaml파일의 spring > datasource 아래있는 내용들을 주입할겁니다. 라고 약속하는것이다.
    따라서 DataSourceBuilder.create().type(HikariDataSource.class).build();

    에 데이터베이스의 정보를 적어주지 않아도 위의 h2 데이터베이스 설정값들이 주입되어 h2dataSource라는 이름의 객체가 Bean으로 등록된다.

  1. Member Domain 객체 추가

Member 코드

@Getter
@Setter
public class Member {

    private Long id;
    private String name;

    public Member(Long id, String name) {
        this.id = id;
        this.name = name;
    }
}
  1. MemberRepository 추가

MemberRepository 코드

package hello.springboot.repository;

import com.zaxxer.hikari.HikariDataSource;
import hello.springboot.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;

@Repository
public class MemberRepository {

    private HikariDataSource dataSource;
    private JdbcTemplate jdbcTemplate;

    public HikariDataSource getDataSource() {
        return dataSource;
    }

    public MemberRepository(@Qualifier("mySqldataSource") HikariDataSource dataSource) {
        this.dataSource = dataSource;
        this.jdbcTemplate = new JdbcTemplate(this.dataSource);
    }

    public void insert(Member member){
        jdbcTemplate.update("INSERT INTO MEMBER(NAME) VALUES (?)",member.getName());
    }


}

실제 쿼리를 날리기위해 Repository를 간단히 만들어주고 정의한 datasource 중 원하는 datasource주입시켜준다.

    public MemberRepository(@Qualifier("mySqldataSource") HikariDataSource dataSource) {
        this.dataSource = dataSource;
        this.jdbcTemplate = new JdbcTemplate(this.dataSource);
    }

3번의 DatasourceConfig에서는 HikariDataSource 타입으로 갖는 Bean이 두가지 h2dataSource , mySqldataSource 존재한다.
여기서 선택적으로 판단하기위해 @Qualifier 어노테이션으로 위의 문제를 해결 할 수 있다.

  1. 테스트코드 작성

테스트코드

package hello.springboot.config;

import hello.springboot.domain.Member;
import hello.springboot.repository.MemberRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

@SpringBootTest
@ActiveProfiles("dev")
public class DatasourceConfigTest {

    @Autowired
    private MemberRepository memberRepository;

    @Test
    @DisplayName("insert 테스트")
    void insertTest() {
        Member member = new Member(1L,"sean");
        memberRepository.insert(member);
    }
}

dev 환경이라고 @ActiveProfiles("dev")로 명시하고
@Repository로 등록된 MemberRepositoryBean세팅은 우리가 원한대로 이루어져있다.
아래 코드를 실행하면 제대로 값이 들어간것을 확인 할 수있다.


현재 데이터베이스는 @Qualifier("mySqldataSource")Mysql로 잡혀있지만
h2로 변경을 원하면 @Qualifier("h2dataSource")로만 변경하면된다.

1개의 댓글

comment-user-thumbnail
2024년 5월 23일

감사합니다. 이해하는데 도움이 많이 되었습니다.

답글 달기