마이크로서비스의 관점에서, 하나의 DB만 접근을 하고 기능을 최소화 하면 좋겠지만 종류가 다른 여러가지 DB 혹은, 종류가같지만 데이터 분산을 위해 다른 물리DB에 붙어야 되는 케이스가 생깁니다. |
데이터 베이스를 나누는 기준은 여러가지가 있으며 다음과 같은 패턴으로 나뉠수 있습니다.
그리고 프로젝트에서 분리반영하여 설정하는 방법은 다음 절차를 따릅니다.
크게 3가지 절차만 잘 수행하면 되겠습니다.
먼저 기존, 하나의 DB만 사용하는 케이스를 살펴봅시다
각 설정을 단계별로 살펴보겠습니다.
spring.jpa.properties.hibernate.show_sql=true spring.jpa.properties.hibernate.use_sql_comments=true spring.jpa.properties.hibernate.format_sql=true # For 1 Database #spring.jpa.hibernate.ddl-auto=create #spring.datasource.url=jdbc:mysql://localhost:3306/db_example #spring.datasource.username=psmon #spring.datasource.password=db1234 |
기존에 설정된 ddl-auto설정,접속정보를 우선 제거해야합니다. ddl-auto의 경우 데이터베이스마다 사용전략이
달라지기때문에 관련설정을 제거합니다. 그외에 hiberate 기능은, 별도의 셋팅없이 공통으로 사용가능합니다.
# for Multiple Database ## Primary app.datasource.primary.url=jdbc:postgresql://localhost:5432/db_example app.datasource.primary.username=postgres app.datasource.primary.password=db1234 app.datasource.primary.driver-class-name=org.postgresql.Driver primary.hibernate.hbm2ddl.auto = create primary.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect ## Second app.datasource.second.url=jdbc:mysql://localhost:3306/db_example2 app.datasource.second.username=psmon app.datasource.second.password=db1234 app.datasource.second.driver-class-name=com.mysql.jdbc.Driver second.hibernate.hbm2ddl.auto = create second.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect |
여기서는, db이름을 primary / second 두가지로만 분류하였습니다.
데이터베이스를 나뉘는 기준이 뭐냐에 따라 이름을 달리할수 있으나, 네이밍을 부여하는것은 아주 어려운일입니다.
샘플에서는 primary/second로 각각 두가지 다른 DB ( Postgres / Mysql )를 설정하겠습니다.
JPA가 지원하는 다양한 DB로 설정이 가능하며, 접속정보및 db에 맞는 driver-class-name을 맞추어주어야합니다.
DB사용과 관련된, Entity/Repository를 JAVA의 package경로를 결정하고 그 하위에서만
작업을 하면 되겠습니다. 여기서는 단순하게 data / data2 라고 분류를 하였으며
data = primary , data2 = second 에 각각 연결을 할계획입니다.
entity와 repository도 분리가 가능하지만, 2가지DB에 4가지 경로가 나오기때문에
여기서는 퉁쳐서 두가지 경로만 사용하겠습니다.
package com.example.demo.config; import java.util.HashMap; import javax.persistence.EntityManagerFactory; import org.springframework.beans.factory.annotation.Qualifier; |
primary db와 나머지 db들( 더 복수개로 설정하고 싶을때) 약간의 차이가 있으니
db를 더 추가하고 싶으면 second 설정내용을 복사하여 db추가를 하면되겠습니다.
하나의 Class에 다중 DB설정화도 가능하지만, 여기서는 Db별로 각각 분리를 하겠습니다.
각각의 DB설정롤을 정의하는 Class
@Configuration @EnableTransactionManagement @EnableJpaRepositories( basePackages = {"com.example.demo.data"}) public class DataBaseConfigPrimary { @Primary @Bean(name = "dataSource") @ConfigurationProperties(prefix = "app.datasource.primary") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Primary @Bean(name = "entityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("dataSource") DataSource dataSource, Environment env) { Map<String, Object> properties = new HashMap<String, Object>(); properties.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("primary.hibernate.hbm2ddl.auto")); properties.put("hibernate.dialect", env.getRequiredProperty("primary.hibernate.dialect")); return builder .dataSource(dataSource) .packages("com.example.demo.data") .persistenceUnit("primary") .properties(properties) .build(); } @Primary @Bean(name = "transactionManager") public PlatformTransactionManager transactionManager( @Qualifier("entityManagerFactory") EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } } |
중요 설정 :
com.example.demo.data : 패키지경로 설정
prefix = "app.datasource.primary" : application.conf에서 사용되는 prefix
"hibernate.hbm2ddl.auto", "create"
@Configuration @EnableTransactionManagement @EnableJpaRepositories( entityManagerFactoryRef = "secondEntityManagerFactory", transactionManagerRef = "secondTransactionManager", basePackages = {"com.example.demo.data2"}) public class DataBaseConfigSecond { @Bean(name = "secondDataSource") @ConfigurationProperties(prefix = "app.datasource.second") public DataSource secondDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "secondEntityManagerFactory") public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory( EntityManagerFactoryBuilder builder, @Qualifier("secondDataSource") DataSource secondDataSource, Environment env) { Map<String, Object> properties = new HashMap<String, Object>(); properties.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("second.hibernate.hbm2ddl.auto")); properties.put("hibernate.dialect", env.getRequiredProperty("second.hibernate.dialect")); return builder .dataSource(secondDataSource) .packages("com.example.demo.data2") .persistenceUnit("second") .properties(properties) .build(); } @Bean(name = "secondTransactionManager") public PlatformTransactionManager secondTransactionManager( @Qualifier("secondEntityManagerFactory") EntityManagerFactory secondEntityManagerFactory) { return new JpaTransactionManager(secondEntityManagerFactory); } } |
중요 설정 :
com.example.demo.data2 : 패키지경로 설정
prefix = "app.datasource.second" : application.conf에서 사용되는 prefix
"hibernate.hbm2ddl.auto", "create" : ddl설정
아래와같은 초기화 시도가 성공하고,에러없이 테이블을 자동으로 잘 만들어낸다고 하면
성공입니다.
Initialized JPA EntityManagerFactory for persistence unit 'primary' Initialized JPA EntityManagerFactory for persistence unit 'second' |
실제 작동되는 코드는 아래 샘플 코드에서 확인이 가능합니다.
http://git.webnori.com/projects/WEBF/repos/spring_jpa/browse