네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

- Spring Data JPA

- Spring Boot

 

 

application.yml

spring:
  datasource:
    hikari:
      bootdb1:
        driver-class-name: [driver-name]
        jdbc-url: [url]
        username: [username]
        password: [password]
      bootdb2:
        driver-class-name: [driver-name]
        jdbc-url: [url]
        username: [username]
        password: [password]

 

* 정의해야 하는 것

- DataSource

- EntityManagerFactory

- TransactionManager

=> DBConfig를 만들어주자.

 

LegacyDBConfig.java

package com.jiyoon.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "legacyEntityManager",
        transactionManagerRef = "legacyTransactionManager",
        basePackages = "com.jiyoon.repository.legacy"
)
public class LegacyDBConfig { 

    @Bean
    @ConfigurationProperties("spring.datasource.hikari.bootdb2")
    public DataSource legacyDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public PlatformTransactionManager legacyTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(legacyEntityManager().getObject());

        return transactionManager;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean legacyEntityManager() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(legacyDataSource());
        em.setPackagesToScan("com.jiyoon.model.legacy");

        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(adapter);
        Map<String, Object> properties = new HashMap<>();
        properties.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
        properties.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
        em.setJpaPropertyMap(properties);

        return em;
    }
}

 

TargetDBConfig.java

package com.jiyoon.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "targetEntityManager",
        transactionManagerRef = "targetTransactionManager",
        basePackages = "com.jiyoon.repository.target"
)
public class TargetDBConfig {

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.hikari.bootdb1")
    public DataSource targetDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public PlatformTransactionManager targetTransactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(targetEntityManager().getObject());

        return transactionManager;
    }

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean targetEntityManager() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(targetDataSource());
        em.setPackagesToScan("com.jiyoon.model.target");

        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(adapter);
        Map<String, Object> properties = new HashMap<>();
        properties.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
        properties.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
        em.setJpaPropertyMap(properties);

        return em;
    }
}

 

@ConfigurationProperties 과 관련 글

https://frogand.tistory.com/131

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config

 

Core Features

Spring Boot lets you externalize your configuration so that you can work with the same application code in different environments. You can use a variety of external configuration sources, include Java properties files, YAML files, environment variables, an

docs.spring.io

 

* 트랜잭션

여러 단계를 수행할 때, 하나라도 실패하면 모두 취소되어야 하며 데이터의 무결성을 보장한다.

 

* 스프링의 트랜잭션 지원

선언적 트랜잭션을 지원한다. 트랜잭션의 범위를 코드 수준으로 정의 가능하며 설정 파일 또는 어노테이션을 이용하여 규칙 및 범위를 설정할 수 있다.

 

- PlatformTransactionManager

트랜잭션은 PlatformTransactionManager 인터페이스를 이용해 추상화했다. DB 연동 기술에 따라 각각의 구현 클래스가 제공된다.

실제 트랜잭션을 처리할 때 PlatformTransactionManager를 사용하진 않는다. 선언적 트랜잭션 방식으로 처리한다.

- JDBC 기반의 트랜잭션 설정

JDBC, MyBatis 등의 JDBC를 이용하는 경우 DataSourceTransactionManager를 관리자로 등록한다.

dataSource 프로퍼티를 통해 전달받은 Connection으로 commit, rollback을 수행하면서 관리한다.

- JPA 트랜잭션 설정

JPA를 사용하는 경우 JpaTransactionManager를 사용한다.

 

 

엔티티

package com.jiyoon.model.legacy

@Entity
@Table(schema = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    
    private String name;
}

 

JPA 레포지토리

package com.jiyoon.repository.legacy;

public interface UserRepository extends JpaRepository<User, Integer> {}

 

 

출처

https://www.baeldung.com/spring-data-jpa-multiple-databases

 

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !