[springboot] jpa multiple datasource

- Goal

JPA를 사용할 때 여러 데이터베이스에 접속해야 하는 경우 필요한 설정


- Time

15min


- Enviroment

springboot 1.5, java 1.8, STS3.7, maven


- Tutorial

핵심은 JPA repository를 관리하는 설정을 필요한 데이터베이스 수만큼 생성해 놓고 사용한다. 


자세한 소스는 아래 github에서 확인 할 수 있다. 

https://github.com/beans9/springboot-jpa-multiple-datasource


application에 alpha에 url과 beta에 url을 따로 설정해 놓는다. 

(편의상 데이터베이스는 H2를 사용한다.)


application.properties

jdbc.driverClassName=org.h2.Driver


spring.h2.console.enabled=true

spring.h2.console.path=/h2-console


user.jdbc.alpha.url=jdbc:h2:~/alpha

user.jdbc.beta.url=jdbc:h2:~/beta


hibernate.hbm2ddl.auto=update



Entity 모델을 생성한다. 


User.java

package com.example.model;


@Entity

@Data

public class User {

@GeneratedValue

@Id

private int id;

String name;

}



Repository Interface를 생선한다. 편의상 alpha와 beta를 구분해서 만드는게 좋다. 

(모델은 동일하게 User를 사용한다.)


UserRepoAlpha.java

com.example.repo.alpha


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


UserRepoBeta.java

com.example.repo.beta


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



Config파일을 생성한다. 

basePackages  = Repository로 사용할 패키지명을 적는다. 

파란글씨부분에 사용할 Entity 패키지를 적는다. (중복되어도 상관없다.)

메인 DataConfig에 @Primary를 선언해 준다. 



AlphaConfig.java

package com.example.config;


@Configuration

@PropertySource({"classpath:application.properties"})

@EnableJpaRepositories(

basePackages = "com.example.repo.alpha",

entityManagerFactoryRef = "alphaEntityManager",

transactionManagerRef = "alphaTransactionManager"

)

public class AlphaConfig {

    @Autowired

    private Environment env;

     

    @Bean

    @Primary

    public LocalContainerEntityManagerFactoryBean alphaEntityManager() {

        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();

        em.setDataSource(alphaDataSource());

        em.setPackagesToScan(new String[] { "com.example.model" });

 

        HibernateJpaVendorAdapter vendorAdapter= new HibernateJpaVendorAdapter();

        em.setJpaVendorAdapter(vendorAdapter);

        HashMap<String, Object> properties = new HashMap<>();

        properties.put("hibernate.hbm2ddl.auto",env.getProperty("hibernate.hbm2ddl.auto"));

        properties.put("hibernate.dialect",env.getProperty("hibernate.dialect"));

        em.setJpaPropertyMap(properties);

 

        return em;

    }

 

    @Primary

    @Bean

    public DataSource alphaDataSource() {

  

        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));

        dataSource.setUrl(env.getProperty("user.jdbc.alpha.url"));

        dataSource.setUsername(env.getProperty("jdbc.user"));

        dataSource.setPassword(env.getProperty("jdbc.pass"));

 

        return dataSource;

    }

 

    @Primary

    @Bean

    public PlatformTransactionManager alphaTransactionManager() {

  

        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory(alphaEntityManager().getObject());

        return transactionManager;

    }

}


위와 거의 동일하게 Beta DB에 대한 설정을 해준다. 

@Primary가 삭제되고 entityManagerFactoryRef와 transactionManagerRef 명이 변경되었다. 

basePackages와 DataSource에 Url을 다르게 함으로써 다른 DB 사용을 선언해 준다. 


BetaConfig.java

@Configuration

@PropertySource({"classpath:application.properties"})

@EnableJpaRepositories(

basePackages = "com.example.repo.beta",

entityManagerFactoryRef = "betaEntityManager",

transactionManagerRef = "betaTransactionManager"

)

public class BetaConfig {

    @Autowired

    private Environment env;

     

    @Bean

    public LocalContainerEntityManagerFactoryBean betaEntityManager() {

        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();

        em.setDataSource(betaDataSource());

        em.setPackagesToScan( new String[] { "com.example.model" });

 

        HibernateJpaVendorAdapter vendorAdapter

          = new HibernateJpaVendorAdapter();

        em.setJpaVendorAdapter(vendorAdapter);

        HashMap<String, Object> properties = new HashMap<>();

        properties.put("hibernate.hbm2ddl.auto",env.getProperty("hibernate.hbm2ddl.auto"));

        properties.put("hibernate.dialect",env.getProperty("hibernate.dialect"));

        em.setJpaPropertyMap(properties);

 

        return em;

    }

 

    @Bean

    public DataSource betaDataSource() {

  

        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));

        dataSource.setUrl(env.getProperty("user.jdbc.beta.url"));

        dataSource.setUsername(env.getProperty("jdbc.user"));

        dataSource.setPassword(env.getProperty("jdbc.pass"));

 

        return dataSource;

    }

 

    @Bean

    public PlatformTransactionManager betaTransactionManager() {

  

        JpaTransactionManager transactionManager = new JpaTransactionManager();

        transactionManager.setEntityManagerFactory(betaEntityManager().getObject());

        return transactionManager;

    }

}



Controller를 생성하고 데이터 입력 테스트를 한다. 


@Controller

public class WebController {

@Autowired

UserRepoAlpha userRepoAlpha;  

@Autowired

UserRepoBeta userRepoBeta;

@RequestMapping("/addAlpha")

@ResponseBody

public User addAlpha(User user){

return userRepoAlpha.save(user);

}

@RequestMapping("/addBeta")

@ResponseBody

public User addBeta(User user){

return userRepoBeta.save(user);

}

}



SpringBoot를 구동시키고 alpha와 Beta에 데이터를 입력한다. 




데이터 입력 후 H2-console에 접속하여 데이터가 제대로 들어갔는지 확인한다. 



각각 DB에 제대로 데이터가 들어간것을 확인 할 수 있다.