복붙노트

[SPRING] 스프링 데이터 소스를 동적으로 변경

SPRING

스프링 데이터 소스를 동적으로 변경

나는 Spring 애플리케이션을 가지고 있는데, 나는 데이터 소스를 동적으로 변경하려고한다. DS URL을 입력하면 스프링 빈과 모든 의존성이 자동으로 업데이트됩니다. 이것은 다소 이상하지만 어쨌든 나는 그것을 달성하기를 원합니다. My Spring 구성은 다음과 같습니다.

<bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
    <property name="serverName" value="${jdbc.serverName}" />
    <property name="portNumber" value="${jdbc.portNumber}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="databaseName" value="${jdbc.databaseName}" />
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="majorDataSource"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager"/>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="majorDataSource"/>
    <property name="configLocation" value="classpath:sqlmap-config.xml"/>
</bean>

질문은 다음과 같습니다.

Spring이 하나의 키를 기반으로 데이터 소스를 동적으로 라우팅 할 수 있다는 것을 알고 있지만, 데이터 소스 URL은 Spring에서 미리 정의되어 있으며 런타임을 변경하지 않습니다. 내 사건이 아니야.

해결법

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

    1.스프링의 AbstractRoutingDataSource를 확장하고 사용할 데이터 소스의 스프링 빈을 참조하는 키를 반환해야하는 decideCurrentLookupKey () 메서드를 재정 의하여이를 사용할 수 있습니다.

    스프링의 AbstractRoutingDataSource를 확장하고 사용할 데이터 소스의 스프링 빈을 참조하는 키를 반환해야하는 decideCurrentLookupKey () 메서드를 재정 의하여이를 사용할 수 있습니다.

    이 기능을 사용하는 방법의 예를 보여주는 스프링 소스의 블로그에서이 블로그 기사를 살펴보십시오.

    기본적으로 여러분의 질문에 답하기 위해, XML 설정에서 두 개의 데이터 소스를 다른 스프링 빈으로 정의하는 것이 필요합니다. 하나를 동적으로 생성 할 필요가 없으며 spring은 양쪽 모두를로드하고 determinCurrentLookupKey () 메소드의 기준에 따라 둘 중 하나를 동적으로 사용합니다.

    이것은 다음과 같이 될 것입니다 :

    XML 설정

    <!-- first data source -->
    <bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
        <property name="serverName" value="${jdbc.major.serverName}" />
        <property name="portNumber" value="${jdbc.major.portNumber}" />
        <property name="user" value="${jdbc.major.username}" />
        <property name="password" value="${jdbc.major.password}" />
        <property name="databaseName" value="${jdbc.major.databaseName}" />
    </bean>
    <!-- second data source -->
    <bean id="minorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
        <property name="serverName" value="${jdbc.minor.serverName}" />
        <property name="portNumber" value="${jdbc.minor.portNumber}" />
        <property name="user" value="${jdbc.minor.username}" />
        <property name="password" value="${jdbc.minor.password}" />
        <property name="databaseName" value="${jdbc.minor.databaseName}" />
    </bean>
    <!-- facade data source -->
    <bean id="dataSource" class="blog.datasource.CustomerRoutingDataSource">
       <property name="targetDataSources">
          <map>
             <entry key="MINOR" value-ref="minorDataSource"/>
             <entry key="MAJOR" value-ref="majorDataSource"/>
          </map>
       </property>
       <property name="defaultTargetDataSource" ref="majorDataSource"/>
    </bean>
    <!-- wiring up -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:sqlmap-config.xml"/>
    </bean>
    

    자바

    public class MyRoutingDataSource extends AbstractRoutingDataSource {
       @Override
       protected Object determineCurrentLookupKey() {
          // get the current url
          HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
          if (request.getRequestURL().toString().endsWith("/minor"))
              return "MINOR";
          else
              return "MAJOR";
       }
    }
    
  2. ==============================

    2.이것이 올바른 방법인지 확실하지 않지만 당신이 할 수있는 일은 이와 같습니다.

    이것이 올바른 방법인지 확실하지 않지만 당신이 할 수있는 일은 이와 같습니다.

    <bean id="majorDataSource" class="org.postgresql.ds.PGSimpleDataSource">
        <property name="serverName" value="dummydata" />
        <property name="portNumber" value="dummydata" />
        <property name="user" value="dummydata" />
        <property name="password" value="dummydata" />
        <property name="databaseName" value="dummydata" />
    </bean>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="majorDataSource"/>
    </bean>
    
    <tx:annotation-driven transaction-manager="transactionManager"/>
    

    및 Java 클래스

    public class TestTransaction {
    
       @Autowired
       private DataSourceTransactionManager manager;
    
       private PlatformTransactionManager transactionManager;
    
       public testExecution(DataSource ds) {
           manager.setDataSource(ds);
           transactionManager = manager;
           TransactionDefinition def = new DefaultTransactionDefinition();
           TransactionStatus status = transactionManager.getTransaction(def);
           try {
               jdbcTemplate.update();
               transactionManager.commit(status);
           } catch (Exception ex) {
               transactionManager.rollback(status);
           }
       }
    }
    

    이 접근법이 내가 아직 봄에 처음이기 때문에 일할 수 있는지 제안 해주십시오.

  3. from https://stackoverflow.com/questions/13507522/dynamically-change-spring-data-source by cc-by-sa and MIT license