현업에서는 여러가지의 데이터베이스를 연결해야하는일이 굉장히 많다.
Properties
를 통한 두개 이상의 데이터베이스를 연결하려면 어떻게 해야할까?
mysql
, h2
database를 사용하여 Member객체를 insert 하는 예제를 들어보겠습니다.
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에 있는것들을 추가해주면 된다.
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를 어떻게 쓰겠다 정의한것이다.
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
, mysql
의 connection을 도와주는 것이라고 생각하면된다.
@Profile("dev")
로 표시한것이다.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으로 등록된다.
Member 코드
@Getter
@Setter
public class Member {
private Long id;
private String name;
public Member(Long id, String name) {
this.id = id;
this.name = name;
}
}
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
어노테이션으로 위의 문제를 해결 할 수 있다.
테스트코드
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
로 등록된 MemberRepository
의 Bean세팅은 우리가 원한대로 이루어져있다.
아래 코드를 실행하면 제대로 값이 들어간것을 확인 할 수있다.
현재 데이터베이스는 @Qualifier("mySqldataSource")
로 Mysql로 잡혀있지만
h2로 변경을 원하면 @Qualifier("h2dataSource")
로만 변경하면된다.
감사합니다. 이해하는데 도움이 많이 되었습니다.