JPA를 사용하는 경우 테스트 환경에 따라서 Profile에 따라 다른 Database를 적용하고 싶은 경우가 있습니다. 예를 들어 로컬 테스트는 H2 Memory DB로 테스트하고 실제 통합 테스트는 Postrgres로 테스트하는 경우에 해당합니다.

Profile별 Database의 속성 정의하기

데이터베이스에 따라서 JDBC 및 JPA의 경우 Dialect가 모두 다르므로 다음과 같이 /src/main/resources/persistence-<PROFILE>.properties  형식으로 데이터베이스 관련 설정 파일을 추가합니다.

persistence-postgres.properties 파일을 경우 다음과 같이 작성할 수 있습니다(아래의 경우 Log4JDBC를 지정하여 선택한 경우).

driverClassName=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url=jdbc:log4jdbc:postgresql://localhost:5432/test
username=postgres
password=postgres

hibernate.dialect=org.hibernate.dialect.PostgreSQL95Dialect
hibernate.show_sql=true
hibernate.hbm2ddl.auto=update

Database 별 Boot Configuration 생성하기

Profile에 따라서 데이터베이스 설정 파일을 다르게 적용하고자 하는 경우 다음과 같이 @Configuration 클래스를 각 Profile에 따라서 작성합니다.

@Configuration
@Profile("h2")
@PropertySource("classpath:persistence-h2.properties")
class H2Config {
}

@Configuration
@Profile("hsqldb")
@PropertySource("classpath:persistence-hsqldb.properties")
class HsqldbConfig {
}

@Configuration
@Profile("derby")
@PropertySource("classpath:persistence-derby.properties")
class DerbyConfig {
}

@Configuration
@Profile("sqlite")
@PropertySource("classpath:persistence-sqlite.properties")
class SqliteConfig {
}

@Configuration
@Profile("postgres")
@PropertySource("classpath:persistence-postgres.properties")
class PostgresConfig {
}

데이터소스 생성하기

이제 다음과 같이 데이터베이스 커넥션 및 Persistence Framework을 초기화합니다.

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

@Configuration
@EnableJpaRepositories(basePackages = "io.datadynamics.demo.spring.rest.books.repositories")
public class DbConfig {

    @Autowired
    private Environment env;

    @Bean
    public DataSource dataSource() {
        final DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("driverClassName"));
        dataSource.setUrl(env.getProperty("url"));
        dataSource.setUsername(env.getProperty("user"));
        dataSource.setPassword(env.getProperty("password"));
        return dataSource;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { "io.datadynamics.demo.spring.rest.books.models" });
        em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        em.setJpaProperties(additionalProperties());
        return em;
    }

    final Properties additionalProperties() {
        final Properties hibernateProperties = new Properties();
        if (env.getProperty("hibernate.hbm2ddl.auto") != null) {
            hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        }
        if (env.getProperty("hibernate.dialect") != null) {
            hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
        }
        if (env.getProperty("hibernate.show_sql") != null) {
            hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        }
        return hibernateProperties;
    }

}