기존 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 선언에 대한 설정을 잘 살펴보시길 바라겠습니다.
'Delvelopment > Spring' 카테고리의 다른 글
[Spring] WebFlux EventLoop (Non Blocking) (0) | 2022.12.04 |
---|---|
[Spring Hibernate] java.sql.SQLSyntaxErrorException: Unknown table 'SEQUENCES' in information_schema Error (0) | 2022.05.04 |
[Spring, Java] SLF4J Logger 올바른 사용법. (log4j2, logback) (0) | 2021.11.20 |
[Spring] 트랜잭션 설정 propagation (전파속성) (0) | 2021.03.19 |
JSP/JSTL 태그, 내장함수 ( <c:if>, <c:choose>, fn:length() 등...) (0) | 2020.04.19 |
댓글