새로운 매니저 사이트를 작업하면서 한 서비스에 다른 여러개의 DB 를 접속시켜야되는 이슈가 발생하였습니다.
예를 들어, DB 접속정보가 따로 관리되는 채소과게와 과일가게의 매출 통계를 구하는 화면이 동일한 화면에 공존할 수 있어야 하는겁니다.
물론, 별도의 서버를 가지고 채소과게 서버와 과일가게 서버를 연달아 호출하는 방법도 있지만 기능이 동일하고 단순 DB 만 다른 경우라면 관리적인 측면에서는 같은 서버에 DB 를 2개 관리하는 것이 훨씬 유리합니다.
한 Spring boot 서버에서 2개의 Mysql DB Connection 을 가지도록 설정해보도록 하겠습니다.
1. application.yml 의존성 주입 설정
spring
FruitShop:
datasource:
jdbc-url: connection 정보
driver-class-name: com.mysql.cj.jdbc.Driver
username: user 이름
password: user 패스워드
vegetableShop:
datasource:
jdbc-url: connection 정보
driver-class-name: com.mysql.cj.jdbc.Driver
username: user 이름
password: user 패스워드
다음과 같이 spring 밑에 2개의 datasource 를 각 내용과 함께 지정해주면 됩니다.
여기서 주의해야 할 점은 datasource 하위 항목에 url 이 아닌 jdbc-url 을 사용해야 한다는 것
입니다. 만약 url 을 사용한다면오류가 발생합니다.
이런 오류가 발생하는 이유는 HikariCP
의 DatabseURL
설정에서 정의된 변수가 url 이 아닌 jdbcUrl 으로 정의되어 있기 때문
입니다.
단일의 connection 만 가질 떄는 별도의 java 코드로 작성되지 않고 application.yml 에 추가하면 자동으로 url 을 jdbc-url 로 인식하여 주입해주는데, java 코드로 작성한 경우는 수동설정으로
해야하기 때문에 url 을 jdbc-url 로 인식하지 못하는 것
입니다.
따라서, 수동으로 지정해줄 때에는 jdbc-url
로 key 값을 지정해서 입력해주어야합니다.
2. sqlSessionFactory 설정 및 template 설정하여 datasource create 작업
@Configuration
@MapperScan(value = "com.test.api.mapper.first", sqlSessionFactoryRef = "firstSqlSessionFactory")
public class FirstDataSourceConfiguration {
@Primary
@Bean(name = "firstDataSource")
@ConfigurationProperties(prefix = "spring.first.datasource")
public DataSource firstDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "firstSqlSessionFactory")
public SqlSessionFactory firstSqlSessionFactory(@Qualifier("firstDataSource") DataSource firstDataSource,
ApplicationContext applicationContext) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(secondDataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("com.test.api.entity, com.test.api.vo");
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mapper/first/**.xml"));
return sqlSessionFactoryBean.getObject();
}
@Primary
@Bean(name = "firstSessionTemplate")
public SqlSessionTemplate firstSqlSessionTemplate(@Qualifier("firstSqlSessionFactory") SqlSessionFactory firstSqlSessionFactory) {
return new SqlSessionTemplate(firstSqlSessionFactory);
}
}
@Configuration
@MapperScan(value = "com.paymint.api.mapper.second", sqlSessionFactoryRef = "secondSqlSessionFactory")
public class SecondDataSourceConfiguration {
@Bean(name = "SecondDataSource")
@ConfigurationProperties(prefix="spring.second.datasource")
public DataSource SecondDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondSqlSessionFactory")
public SqlSessionFactory secondSqlSessionFactory(@Qualifier("secondDataSource") DataSource secondDataSource,
ApplicationContext applicationContext) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(secondDataSource);
sqlSessionFactoryBean.setTypeAliasesPackage("com.test.api.entity, com.test.api.vo");
sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mapper/second/**.xml"));
return sqlSessionFactoryBean.getObject();
}
@Bean(name = "secondSessionTemplate")
public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory") SqlSessionFactory secondSqlSessionFactory) {
return new SqlSessionTemplate(secondSqlSessionFactory);
}
}
첫번 째로 설정한 application.yml 의 속성값을 토대로 위 내용과 같이 작성해주면 됩니다.
SqlSessionFactory 와 SqlSessionTemplate 에 대한 자세한 설명은 다음 사이트에 자세히 설명되어있습니다.
참고 사이트 : Mybatis개념 및 핵심 정리
SqlSessonFactory
와 SqlSessionTemplate
를 설정해줄 때 파라미터를 @Qualifier
로 지정해 주지 않으면 두개의 config 파일에서 발생한 SqlSessionFactory
를 제대로 찾지 못해 오류가 발생하므로 꼭 명시해 줘야합니다.
또한, @Primary
은 default
로 사용하고자 하는 Datasource
를 지정해줍니다. 만약 지정해주지 않는다면 우선적으로 실행해야할 Datasource 를 지정해주지 못해 혼란을 야기시켜 오류가 발생할 수 있습니다.
주의 해야될 사항으로는 SessionFactory 에 저장할 config 를 설정 시 Mapper 에서 사용하고자하는 VO
및 Entity
에 대해서는 setTypeAliasesPackage
로 지정해주셔야 합니다. 만약 지정해주지 않는다면 aliases 를 찾지 못해 오류가 발생하게됩니다.
만약 2개의 typeAliasesPackage 를 지정해주기 위해서는 (,) 로 구분하여 다음과 같이저장해주시면 됩니다.
sqlSessionFactoryBean.setTypeAliasesPackage("com.test.api.entity, com.test.api.vo");
그 외에도 sqlSessionFactory 에 관련하여 추가 설정을 할 수 있으니 다음 사이트를 참고하여 설정해준다면 조금 더 많은 기능을 사용할 수 있을 것입니다.
또한, classPath
설정 시 특정한 설정을 하시지 않았다면 default 로 resourece
가 경로가 지정되는데, 이에 따른 경로에 상대 경로에 맞춰 디렉터리와 파일 확장자명에 따른 파일명을 정확하게 지정해 주셔야합니다.
마무리로 한 서버에서 2개 이상의 Datasource 를 지정해주기 위한 방법에 대해서 말씀드렸습니다. 설정하는 것는 크게 어렵지 않지만, jdbc-url
이나 classPah
, typealiasesPackage
와 같은 주의사항들을 잘 설정해주지 않으면 오류도 명확하지 않아 쉽게 해맬 수 있으니 주의하셔서 설정하여 적은 삽질(?)을 통해 설정하실 수 있습니다.
Reference
- https://www.devglan.com/spring-boot/spring-boot-multiple-database-configuration
- https://medium.com/@joeclever/using-multiple-datasources-with-spring-boot-and-spring-data-6430b00c02e7
- https://supawer0728.github.io/2018/03/22/spring-multi-transaction/
- https://www.holaxprogramming.com/2015/10/10/spring-boot-multi-datasources/
- https://jojoldu.tistory.com/296
- https://gmlwjd9405.github.io/2018/05/15/setting-for-db-programming.html
- https://wickedmagic.tistory.com/299
- https://mybatis.org/mybatis-3/ko/configuration.html#objectFactory
- https://cpdev.tistory.com/76
'SPRING' 카테고리의 다른 글
[Spring] Meta Annotation 이란?(@Target, @Retention) (4) | 2020.07.25 |
---|---|
[Spring Boot] @NotNull, @NotEmpty, @NotBlank 의 차이점 및 사용법 (6) | 2020.04.01 |
[Spring] Maven Wrapper 설명 및 실행방법 (1) | 2020.01.31 |
[Spring boot] java 파일을 특정 패키지로 이동 시 발생하는 ConflictingBeanDefinitionException 문제 해결 (9) | 2020.01.03 |
[Spring boot] TestRestTemplate 401(authentication) 오류 발생해결 (0) | 2019.10.05 |