복붙노트

[SPRING] 동적 데이터 소스로 Spring AbstractRoutingDataSource를 사용하는 방법?

SPRING

동적 데이터 소스로 Spring AbstractRoutingDataSource를 사용하는 방법?

나는 Spring, Spring Data JPA, Spring Security, Primefaces를 사용하는 프로젝트에서 일하고있다.

나는 봄과 함께 동적 데이터 소스 라우팅에 관한이 튜토리얼을 따르고 있었다.

이 자습서에서는 미리 정의 된 데이터 소스간에 동적 데이터 소스 전환 만 수행 할 수 있습니다.

다음은 내 코드 스 니펫입니다.

봄 Context-jpa.xml

<bean id="dsCgWeb1" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName.Cargest_web}"></property>
    <property name="url" value="${jdbc.url.Cargest_web}"></property>
    <property name="username" value="${jdbc.username.Cargest_web}"></property>
    <property name="password" value="${jdbc.password.Cargest_web}"></property>
</bean>

<bean id="dsCgWeb2" class="org.apache.commons.dbcp.BasicDataSource">
    // same properties, different values ..
</bean>

<!--  Generic Datasource [Default : dsCargestWeb1]  -->
<bean id="dsCgWeb" class="com.cargest.custom.CargestRoutingDataSource">
    <property name="targetDataSources">
        <map>
            <entry key="1" value-ref="dsCgWeb1" />
            <entry key="2" value-ref="dsCgWeb2" />
        </map>
    </property>
    <property name="defaultTargetDataSource" ref="dsCgWeb1" />
</bean>

내가하고 싶은 일은 targetDataSources 맵을 그 요소와 같이 동적으로 만드는 것입니다.

즉, 특정 데이터베이스 테이블을 가져오고 해당 테이블에 저장된 속성을 사용하여 내 데이터 소스를 작성한 다음 targetDataSources와 같은 맵에 저장하려고합니다.

이것을 할 수있는 방법이 있습니까?

해결법

  1. ==============================

    1.AbstractRoutingDataSource의 아무 것도 DataSourceS의 정적지도를 사용하도록 강요하지 않습니다. Map 를 구현하는 bean을 구성하는 것은 여러분의 책임입니다. key는 DataSource를 선택하기 위해 사용하고, value는 DataSource이거나 JNDI가 정의한 데이터 소스를 참조하는 String (기본값)입니다. 지도가 메모리에 저장 될 때 AbstractRoutingDataSource가 캐싱을하지 않으므로 동적으로 수정할 수도 있습니다.

    AbstractRoutingDataSource의 아무 것도 DataSourceS의 정적지도를 사용하도록 강요하지 않습니다. Map 를 구현하는 bean을 구성하는 것은 여러분의 책임입니다. key는 DataSource를 선택하기 위해 사용하고, value는 DataSource이거나 JNDI가 정의한 데이터 소스를 참조하는 String (기본값)입니다. 지도가 메모리에 저장 될 때 AbstractRoutingDataSource가 캐싱을하지 않으므로 동적으로 수정할 수도 있습니다.

    전체 예제 코드가 없습니다. 그러나 내가 상상할 수있는 것은 여기있다. 웹 응용 프로그램에서 클라이언트 당 하나의 데이터베이스가 있습니다. 모두 동일한 구조입니다. 예를 들어, 단지 이상한 디자인이라고 할 수 있습니다. 로그인 할 때, 애플리케이션은 클라이언트 용 데이터 소스를 생성하고이를 sessionId에 의해 색인 된 맵에 저장한다. map은 루트 콘텍스트 인 dataSources에있는 빈이다.

    @Autowired
    @Qualifier("dataSources");
    Map<String, DataSource> sources;
    
    // I assume url, user and password have been found from connected user
    // I use DriverManagerDataSource for the example because it is simple to setup
    DataSource dataSource = new DriverManagerDataSource(url, user, password);
    sources.put(request.getSession.getId(), dataSource);
    

    또한 destroy 메소드에서 dataSources를 정리하는 세션 리스너가 필요합니다.

    @Autowired
    @Qualifier("dataSources");
    Map<String, DataSource> sources;
    
    public void sessionDestroyed(HttpSessionEvent se)  {
        // eventually cleanup the DataSource if appropriate (nothing to do for DriverManagerDataSource ...)
        sources.remove(se.getSession.getId());
    }
    

    라우팅 데이터 소스는 다음과 같을 수 있습니다.

    public class SessionRoutingDataSource extends AbstractRoutingDataSource {
    
        @Override
        protected Object determineCurrentLookupKey() {
            HttpServletRequest request = ((ServletRequestAttributes)
                    RequestContextHolder.getRequestAttributes()).getRequest();
            return request.getSession().getId();
        }
    
        @Autowired
        @Qualifier("dataSources")
        public void setDataSources(Map<String, DataSource> dataSources) {
            setTargetDataSources(dataSources);
    }
    

    다른 데이터베이스를 설정하는 데 많은 작업이 필요하기 때문에 아무것도 테스트하지 않았지만 괜찮을 것입니다. 실제로는 세션 당 데이터 소스가 다르지 않지만 사용자 당 세션 수가 다른 사용자 당 하나의 데이터 소스가있을 수는 있지만 간단히 말하면 단순한 예입니다.

  2. from https://stackoverflow.com/questions/26176439/how-to-use-spring-abstractroutingdatasource-with-dynamic-datasources by cc-by-sa and MIT license