본문 바로가기
Delvelopment/Spring

[Spring] multiple Datasource 설정과 JPA와 Mybatis 연동 그리고 Querydsl 설정까지 (h2, mysql, mssql, rds)

by 제제킴 2022. 5. 4.
반응형

기존 JPA에 RDS를 주로 개발하던 도중. 레거시 시스템의 db 연동이 필요한 시점이 왔다.
데이터 마이그를 하고싶은데 백오피스에 대한 대응을 내가 다 할 수 없으니.. 뭐 어쩌겠어.. 데이터 넣어줘야지
그래서 multi datasource에 대한 작업을 시작..

우선 설정에 필요한 내용은. 

  • Database 정보
  • JPA에서 사용할 Entity Package 경로
  • Hibernate 설정
  • Mybais 에서 사용할 mapper package 경로

 

application.yml
Database 정보들이 필요하다. 

spring:
  config:
    activate:
      on-profile: local
  datasource:
    jdbc-url: jdbc:mysql://
    username: 
    password: 
    driver-class-name: com.mysql.cj.jdbc.Driver
  mssql-datasource:
    jdbc-url: 
    username: 
    password: 
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver


----
  h2-datasource:
    jdbc-url: 
    username: 
    password:
    driver-class-name: org.h2.Driver

 

Hibernate와 Mybatis에 대한 설정을 진행한다.
hbm2ddl, dialect, show_sql 등의 관련 설정들을 셋팅해주면 된다.
여기서 주의할 점은 dialect에 알맞은 Tager Database를 잘 설정해줘야 한다.
JPA에서 1개의 datasource만 설정할때는 application.yml에 있는 정보를 사용하지만 EntityManager가 분리되었을때는 Bean에 설정되는 정확한 값을 입력해줘야 한다.

public class DatabaseConfig extends HikariConfig {

    protected void setConfigureEntityManagerFactory(LocalContainerEntityManagerFactoryBean factory) {
        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setJpaPropertyMap(Map.of("hibernate.hbm2ddl.auto", "none",
                "hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect",
                "hibernate.show_sql", "true",
                "hibernate.format_sql", "true"));
        factory.afterPropertiesSet();
    }

    protected void setConfigureSqlSessionFactory(SqlSessionFactoryBean sessionFactoryBean, DataSource dataSource) throws IOException {
        sessionFactoryBean.setDataSource(dataSource);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mybatis/mapper/**/*.xml"));
    }

}

 

JPA에 EntityMangerFactory에 대한 설정이다.
Bean에 DataSource들을 생성하고, Entity Package 경로에 대해 설정이 필요하다.

@Primary 어노테이션은 Master가 되는 DataSource를 지정하면 된다. 
(단, 두번째, 세번째 DataSource에는 제거 되야한다.)

@EnableJpaRepositories에는 JPA 설정에 관련된 정보들을 입력한다.

@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
@EnableJpaRepositories(
        basePackages = "com.jj.auth.repository",
        entityManagerFactoryRef = "rdsEntityManagerFactory",
        transactionManagerRef = "rdsTransactionManager"
)
public class RdsConfig extends DatabaseConfig {

    final String RDS_DATA_SOURCE = "rdsDataSource";
    final String RDS_MANAGER_FACTORY = "rdsEntityManagerFactory";
    final String RDS_TRANSACTION_MANAGER = "rdsTransactionManager";

    @Bean(name = RDS_DATA_SOURCE)
    public DataSource dataSource() {
        return new LazyConnectionDataSourceProxy(new HikariDataSource(this));
    }

    @Bean(name = RDS_MANAGER_FACTORY)
    @Primary
    public EntityManagerFactory entityManagerFactory(@Qualifier(RDS_DATA_SOURCE) DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(dataSource);
        factory.setPackagesToScan("com.jj.auth.model");
        factory.setPersistenceUnitName("rdsEntityManager");
        setConfigureEntityManagerFactory(factory);
        return factory.getObject();
    }

    @Bean(name = RDS_TRANSACTION_MANAGER)
    @Primary
    public PlatformTransactionManager transactionManager(@Qualifier(RDS_MANAGER_FACTORY) EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(entityManagerFactory);
        return tm;
    }
}

 

Mybatis에 대한 설정이다.
MapperScan에 대한 Packager 경로와 Bean 네임만 충돌없이 만들어 주면된다.
Mybatis는 SessionFactory를 통해 관리를 하기 때문에 해당 설정을 해주면 된다.

@Configuration
@ConfigurationProperties(prefix = "spring.mssqldatasource")
@MapperScan(
        basePackages = {"com.jj.auth.dao"}
)
public class MsSqlConfig extends DatabaseConfig {

    final String MSSQL_DATA_SOURCE = "mssqlDataSource";
    final String MSSQL_SESSION_FACTORY = "mssqlSessionFactory";
    final String MSSQL_SESSION_TEMPLATE = "mssqlSqlSessionTemplate";

    @Bean(name = MSSQL_DATA_SOURCE)
    public DataSource dataSource() {
        return new LazyConnectionDataSourceProxy(new HikariDataSource(this));
    }

    @Bean(name = MSSQL_SESSION_FACTORY)
    public SqlSessionFactory sqlSessionFactory(@Qualifier(MSSQL_DATA_SOURCE) DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        setConfigureSqlSessionFactory(sessionFactoryBean, dataSource);
        return sessionFactoryBean.getObject();
    }

    @Bean(name = MSSQL_SESSION_TEMPLATE)
    public SqlSessionTemplate firstSqlSessionTemplate(@Qualifier(MSSQL_SESSION_FACTORY) SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

 

마지막으로 Querydsl에 대한 설정까지 추가해주면 된다.
PersistenceContext에 Bean 설정을 해주면 된다.

@Configuration
public class QuerydslConfig {
    @PersistenceContext(unitName = "rdsEntityManagerFactory")
    private EntityManager entityManager;

    @Bean
    public JPAQueryFactory jpaQueryFactory() {
        return new JPAQueryFactory(this.entityManager);
    }
}

 

 


Querydsl은 추가적으로 필요하신 분만 설정하시면 됩니다.

셋팅 도중 FactoryManger와 같은 error들이 발생한다면 db셋팅이 잘됬는지 확인해보시면 좋으며,
Bean 생성 및 Bean을 찾지 못한다면 Bean 네이밍 또는 Bean 선언에 대한 설정을 잘 살펴보시길 바라겠습니다.

반응형

댓글