본문 바로가기

SPRING

[Mybatis] Spring boot 에서 mybatis 로 2개의 DB connection 하기

 

새로운 매니저 사이트를 작업하면서 한 서비스에 다른 여러개의 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 을 사용한다면오류가 발생합니다.

이런 오류가 발생하는 이유는 HikariCPDatabseURL 설정에서 정의된 변수가 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개념 및 핵심 정리

 

[MyBatis] MyBatis란? 개념 및 데이터구조

MyBatis란? 객체 지향 언어인 자바의 관계형 데이터베이스 프로그래밍을 좀 더 쉽게 할 수 있게 도와 주는 개발 프레임 워크로서 JDBC를 통해 데이터베이스에 엑세스하는 작업을 캡슐화하고 일반 SQL 쿼리, 저장..

khj93.tistory.com

SqlSessonFactorySqlSessionTemplate 를 설정해줄 때 파라미터를 @Qualifier 로 지정해 주지 않으면 두개의 config 파일에서 발생한 SqlSessionFactory 를 제대로 찾지 못해 오류가 발생하므로 꼭 명시해 줘야합니다.

 

또한, @Primarydefault 로 사용하고자 하는 Datasource 를 지정해줍니다. 만약 지정해주지 않는다면 우선적으로 실행해야할 Datasource 를 지정해주지 못해 혼란을 야기시켜 오류가 발생할 수 있습니다.

주의 해야될 사항으로는 SessionFactory 에 저장할 config 를 설정 시 Mapper 에서 사용하고자하는 VOEntity 에 대해서는 setTypeAliasesPackage 로 지정해주셔야 합니다. 만약 지정해주지 않는다면 aliases 를 찾지 못해 오류가 발생하게됩니다.

만약 2개의 typeAliasesPackage 를 지정해주기 위해서는 (,) 로 구분하여 다음과 같이저장해주시면 됩니다.

sqlSessionFactoryBean.setTypeAliasesPackage("com.test.api.entity, com.test.api.vo");

 

그 외에도 sqlSessionFactory 에 관련하여 추가 설정을 할 수 있으니 다음 사이트를 참고하여 설정해준다면 조금 더 많은 기능을 사용할 수 있을 것입니다.

http://mybatis.org/spring/apidocs/reference/org/mybatis/spring/SqlSessionFactoryBean.html#setTypeAliasesPackage(java.lang.String)

 

또한, classPath 설정 시 특정한 설정을 하시지 않았다면 default 로 resourece 가 경로가 지정되는데, 이에 따른 경로에 상대 경로에 맞춰 디렉터리와 파일 확장자명에 따른 파일명을 정확하게 지정해 주셔야합니다.

마무리로 한 서버에서 2개 이상의 Datasource 를 지정해주기 위한 방법에 대해서 말씀드렸습니다. 설정하는 것는 크게 어렵지 않지만, jdbc-url 이나 classPah, typealiasesPackage 와 같은 주의사항들을 잘 설정해주지 않으면 오류도 명확하지 않아 쉽게 해맬 수 있으니 주의하셔서 설정하여 적은 삽질(?)을 통해 설정하실 수 있습니다.



 

 

Reference

  • 박기현 2021.06.05 10:11

    잘 참고하였습니다.

    오탈자 있어서 코멘트 남김니다

    @Bean(name = "SecondDataSource") -> @Bean(name = "secondDataSource")

    그리고

    sqlSessionFactoryBean.setDataSource(secondDataSource); 이게 두번 쓰엿네요