이로

SPRING JPA 다중DB 접속 본문

컴퓨터/사용했던 기술 정리

SPRING JPA 다중DB 접속

利路 2020. 5. 28. 16:55
반응형

1.요구사항

  • 한 서버가 두 개 이상의 DB와 연결되어 있어야 한다. (필자는 MySQL, PostgreSQL 두 대 연결하였다.)
  • Spring JPA를 사용한다.

 2. 의존성

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

(버전이 없는 이유는 Parent 에서 Spring 의 버전에 따라 두 의존성을 관리해 주기 때문이다.)

 

간략 용어 설명

JPA : JAVA Persistence API 의 줄임말로, 관계형 데이터베이스 관리를 표현하는 자바 API 이다.

Hibernate : 자바를 위한 오픈소스 ORM 프레임워크를 제공한다.

ORM : "관계형 데이터베이서의 구조화된 데이터와 자바와 같은 객체 지향 언어간의 구조적 불이리를 어떻게 해소할 수 있을까?" 라는 질문에서 나온 객체-관계 매핑 프레임워크이다.

Data JPA : JPA 기반의 Repository를 쉽게 구현할 수 있도록 Spring Data에서 제공한다.

Spring Data Jdbc 는 Spring Jdbc와 Spring Data Jpa 사이의 빈 공간 채우기 위해 작성되었다. 자세한 설명은 아래 참고링크 참조

 

3. 구성

기본 원리는 Configuration 으로 각 DB에 접속할 때 사용할 정보를 각 각 설정해서 저장해 두면 된다. 메인으로 사용될 DB에는 Primary설정을 해주면 된다.  먼저 코드를 보면 다음과 같다.

 Master DB

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "mysqlEntityManager", transactionManagerRef = "mysqlTransactionManager", basePackages = "적용할.repository")
public class MasterDBConfig {
    
    @Autowired
    private Environment env;
    
    @Primary
    @Bean
    public DataSource mysqlDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("spring.main.datasource.driverClassName"));
        dataSource.setUrl(env.getProperty("spring.main.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.main.datasource.username"));
        dataSource.setPassword(env.getProperty("spring.main.datasource.password"));
        return dataSource;
    }

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean mysqlEntityManager() {
        LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        HashMap<String, Object> properties = new HashMap<>();
        localContainerEntityManagerFactoryBean.setDataSource(mysqlDataSource());
        localContainerEntityManagerFactoryBean.setPackagesToScan(new String[] { "적용할.엔티티.패키지.entity" });
        localContainerEntityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);       
        properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.main.hibernate.hbm2ddl.auto"));
        properties.put("hibernate.dialect", env.getProperty("spring.main.hibernate.dialect"));
        localContainerEntityManagerFactoryBean.setJpaPropertyMap(properties);
        return localContainerEntityManagerFactoryBean;
    }

    @Primary
    @Bean
    public PlatformTransactionManager mysqlTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(mysqlEntityManager().getObject());
        return transactionManager;
    }
}

 

Sub DB

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "subEntityManager", transactionManagerRef = "subTransactionManager", basePackages = "적용할.repository")
public class DataDBConfig {
	
	@Autowired
	private Environment env;

	@Bean
	public DataSource subDataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();
		
		dataSource.setDriverClassName(env.getProperty("spring.sub.datasource.driverClassName"));
		dataSource.setUrl(env.getProperty("spring.sub.datasource.url"));
		dataSource.setUsername(env.getProperty("spring.sub.datasource.username"));
		dataSource.setPassword(env.getProperty("spring.sub.datasource.password"));

		return dataSource;
	}


	@Bean
	public LocalContainerEntityManagerFactoryBean subEntityManager() {
		LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
		HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
		HashMap<String, Object> properties = new HashMap<>();

		localContainerEntityManagerFactoryBean.setDataSource(subDataSource());
		localContainerEntityManagerFactoryBean.setPackagesToScan("적용할.entity");
		localContainerEntityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
		
		properties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.sub.hibernate.hbm2ddl.auto"));
		properties.put("hibernate.dialect", env.getProperty("spring.sub.hibernate.dialect"));
		
		localContainerEntityManagerFactoryBean.setJpaPropertyMap(properties);

		return localContainerEntityManagerFactoryBean;
	}

	@Bean
	public PlatformTransactionManager subTransactionManager() {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(subEntityManager().getObject());
		return transactionManager;
	}
}

 

application.properties

## MySQL
#spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
spring.main.datasource.url=MySql접속주소
spring.main.datasource.username=MySql접속아이디
spring.main.datasource.password=MySql접속비밀번호
spring.main.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.main.hibernate.hbm2ddl.auto=none
spring.main.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

## PostGreSQL
spring.sub.datasource.url=PostgreSQL접속주소
spring.sub.datasource.username=PostgreSQL접속아이디
spring.sub.datasource.password=PostgreSQL접속비밀번호
spring.sub.datasource.driverClassName=org.postgresql.Driver
spring.sub.hibernate.hbm2ddl.auto=none
spring.sub.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

 

기본적으로 application.properties 에서 설정값을 저장해주고, 그 저장한 값을 각 DB Config 파일의 해당 값에 삽입해주면 된다.

 

정리

  1. 사용할 각 DB 의 DataSource를 생성
  2. 각 각의 EntityManager, TransactionManager를 EntityManagerFactory로 만든다
  3.  @EnableJpaRepositories(entityManagerFactoryRef = "", transactionManagerRef = "", basePackages = "") 설정한다.
    (entityManagerFactoryRef 는 Entity 위치, basePackages 는 연결할 repository 위치)

 

 

참고

반응형

'컴퓨터 > 사용했던 기술 정리' 카테고리의 다른 글

HIGHCHART  (0) 2020.12.14
Httpd Proxy 설정 (하나의 IP 여러 도메인 연결)  (0) 2020.11.24
Comments