2016년 2월 18일 목요일

Spring DataSource Routing

There are some cases that we should use multi datasource.
At that time, we can use spring datasource routing.

- Structure






















- TestApplication.java

package org.blog.test;

import org.blog.test.entity.car.Car;
import org.blog.test.entity.person.Person;
import org.blog.test.model.DBType;
import org.blog.test.model.DataSourceContextHoder;
import org.blog.test.service.car.CarService;
import org.blog.test.service.person.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestApplication implements CommandLineRunner {

    @Autowired
    private PersonService personService;

    @Autowired
    private CarService carService;

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    @Override
    public void run(String... arg0) throws Exception {
        DataSourceContextHoder.setCustomerType(DBType.PERSON);
        Person person = new Person();
        person.setName("person");
        personService.savePerson(person);
        Car car = new Car();
        car.setName("person");
        carService.saveCar(car);

        DataSourceContextHoder.setCustomerType(DBType.CAR);
        Person person1 = new Person();
        person1.setName("car");
        personService.savePerson(person1);
        Car car1 = new Car();
        car1.setName("car");
        carService.saveCar(car1);

        DataSourceContextHoder.setCustomerType(DBType.DEFAULT);
        Person person11 = new Person();
        person11.setName("default");
        personService.savePerson(person11);
        Car car11 = new Car();
        car11.setName("default");
        carService.saveCar(car11);
    }
}

- RoutingDataSource.java

package org.blog.test.component;

import org.blog.test.model.DataSourceContextHoder;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class RoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHoder.getDBType();
    }

}

- DataSourceConfig.java

package org.blog.test.configuration;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.blog.test.component.RoutingDataSource;
import org.blog.test.model.DBType;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource defaultDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "datasource.person")
    public DataSource personDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "datasource.car")
    public DataSource carDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DataSource routeDataSource() {
        RoutingDataSource routeDataSource = new RoutingDataSource();
        routeDataSource.setDefaultTargetDataSource(carDataSource());

        Map targetDataSources = new HashMap<>();         targetDataSources.put(DBType.DEFAULT, defaultDataSource());         targetDataSources.put(DBType.PERSON, personDataSource());         targetDataSources.put(DBType.CAR, carDataSource());          routeDataSource.setTargetDataSources(targetDataSources);         return routeDataSource;     } } 
- Car.java
package org.blog.test.entity.car;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table
@Data
@NoArgsConstructor
public class Car {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column
    private Integer id;

    @Column
    private String name;
}
- Person.java
package org.blog.test.entity.person;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table
@Data
@NoArgsConstructor
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column
    private String name;
}
- DataSourceContextHoder.java
package org.blog.test.model;

public class DataSourceContextHoder {

    private static final ThreadLocal contextHolder = new ThreadLocal<>();

    public static void setCustomerType(DBType dBType) {
        contextHolder.set(dBType);
    }

    public static DBType getDBType() {
        return (DBType) contextHolder.get();
    }

    public static void clearCustomerType() {
        contextHolder.remove();
    }
}
- DBType.java
package org.blog.test.model;

public enum DBType {
    DEFAULT, PERSON, CAR
}
- CarRepository.java
package org.blog.test.repository.car;

import org.blog.test.entity.car.Car;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface CarRepository extends CrudRepository {

}
- PersonRepository.java
package org.blog.test.repository.person;

import org.blog.test.entity.person.Person;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PersonRepository extends CrudRepository {

}
- CarService.java
package org.blog.test.service.car;

import org.blog.test.entity.car.Car;

public interface CarService {

    Car saveCar(Car car);
}
- CarServiceImpl.java
package org.blog.test.service.impl.car;

import org.blog.test.entity.car.Car;
import org.blog.test.repository.car.CarRepository;
import org.blog.test.service.car.CarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CarServiceImpl implements CarService {

    @Autowired
    private CarRepository carRepository;

    @Override
    public Car saveCar(Car car) {
        return carRepository.save(car);
    }

}
- PersonServiceImpl.java
package org.blog.test.service.impl.car;

import org.blog.test.entity.car.Car;
import org.blog.test.repository.car.CarRepository;
import org.blog.test.service.car.CarService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CarServiceImpl implements CarService {

    @Autowired
    private CarRepository carRepository;

    @Override
    public Car saveCar(Car car) {
        return carRepository.save(car);
    }

}
- PersonService.java
package org.blog.test.service.person;

import org.blog.test.entity.person.Person;

public interface PersonService {

    Person savePerson(Person person);
}
- application.properties
==================================================
# DataSource
==================================================
spring.jpa.hibernate.ddl-auto=create-drop

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=user
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

datasource.person.url=jdbc:mysql://localhost/person
datasource.person.username=user
datasource.person.password=password
datasource.person.driver-class-name=com.mysql.jdbc.Driver

datasource.car.url=jdbc:mysql://localhost/car
datasource.car.username=user
datasource.car.password=password
datasource.car.driver-class-name=com.mysql.jdbc.Driver
- pom.xml

 4.0.0
 org.blog.test
 dynamic-datasource-project
 0.1.0

 
  org.springframework.boot
  spring-boot-starter-parent
  1.3.2.RELEASE
 

 
  
   org.springframework.boot
   spring-boot-starter-data-jpa
  
  
   org.springframework.boot
   spring-boot-starter-web
  
  
   org.projectlombok
   lombok
   1.16.6
  
  
   mysql
   mysql-connector-java
  
 

- Execution Result

  - Default DataBase










- Person DataBase









- Car DataBase

댓글 없음 :

댓글 쓰기