Spring 의 AbstractRouting DataSource 를 사용 하여 다 중 데이터 원본 전환 예제 구현
9819 단어 spring다 중 데이터 원본
데이터 원본 전환 을 실현 하 는 기능 은 바로 확장 AbstractRouting DataSource 추상 류 를 사용자 정의 하 는 것 입 니 다.사실은 데이터 원본 DataSourcer 의 경로 중개 에 해당 하 며 프로젝트 가 실 행 될 때 해당 key 값 에 따라 해당 하 는 데이터 원본 DataSource 로 전환 할 수 있 습 니 다.먼저 AbstractRouting DataSource 의 소스 코드 를 보 세 요.
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
/* */
private Map<Object, Object> targetDataSources;
private Object defaultTargetDataSource;
private boolean lenientFallback = true;
private DataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
private Map<Object, DataSource> resolvedDataSources;
private DataSource resolvedDefaultDataSource;
@Override
public Connection getConnection() throws SQLException {
return determineTargetDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return determineTargetDataSource().getConnection(username, password);
}
protected DataSource determineTargetDataSource() {
Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = this.resolvedDataSources.get(lookupKey);
if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
dataSource = this.resolvedDefaultDataSource;
}
if (dataSource == null) {
throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
}
return dataSource;
}
protected abstract Object determineCurrentLookupKey();
}
소스 코드 를 통 해 알 수 있 듯 이 AbstractRouting DataSource 는 AbstractDataSource 를 계승 하고 InitialingBean,AbstractRouting DataSource 의 getConnection()방법 은 determineTargetDataSource()의 이 방법 을 호출 했다.여기 서 determineTargetDataSource()방법 코드 에 중점 을 두 고 determineCurrentLookupkey()방법 을 사용 했다.이것 은 AbstractRouting DataSource 류 의 추상 적 인 방법 이자 데이터 원본 전환 을 실현 하 는 확장 방법 입 니 다.이 방법의 반환 값 은 프로젝트 에 사용 할 DataSource 의 key 값 입 니 다.이 key 를 가 져 오 면 resolvedDataSource 에서 해당 하 는 DataSource 를 꺼 낼 수 있 습 니 다.key 가 해당 하 는 DataSource 를 찾 지 못 하면 기본 데이터 원본 을 사용 합 니 다.사용자 정의 클래스 확장 AbstractRouting DataSource 클래스 는 determineCurrentLookupkey()방법 을 다시 써 서 데이터 원본 전환 기능 을 실현 합 니 다.다음은 사용자 정의 확장 AbstractRouting DataSource 클래스 의 실현 입 니 다.
/**
*
*/
public class MultipleDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getRouteKey();
}
}
DynamicDataSourceHolder 클래스 는 다음 과 같 습 니 다.데이터 원본 에 대한 조작 기능 을 실현 합 니 다.
/**
*
*/
public class DynamicDataSourceHolder {
private static ThreadLocal<String> routeKey = new ThreadLocal<String>();
/**
* key
*/
public static String getRouteKey()
{
String key = routeKey.get();
return key;
}
/**
* key
* removeRouteKey()
*/
public static void setRouteKey(String key)
{
routeKey.set(key);
}
/**
* key
*/
public static void removeRouteKey()
{
routeKey.remove();
}
}
다음은 xml 파일 에 여러 개의 데이터 원본 을 설정 합 니 다:
<!-- -->
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver">
</property>
<property name="url" value="jdbc:jtds:sqlserver://127.0.0.1;databaseName=test">
</property>
<property name="username" value="***"></property>
<property name="password" value="***"></property>
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver">
</property>
<property name="url" value="jdbc:jtds:sqlserver://127.0.0.2:1433;databaseName=test">
</property>
<property name="username" value="***"></property>
<property name="password" value="***"></property>
</bean>
<!-- -->
<bean id="multipleDataSource" class="MultipleDataSource" >
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="dataSource1" key="dataSource1"></entry>
<entry value-ref="dataSource2" key="dataSource2"></entry>
</map>
</property>
<!-- -->
<property name="defaultTargetDataSource" ref="dataSource1" >
</property>
</bean>
여기까지 기본 적 인 설정 이 완성 되 었 습 니 다.다음은 데이터 원본 을 전환 해 야 하 는 곳 에서 호출 방법 을 사용 하면 됩 니 다.보통 dao 층 에서 데이터 베 이 스 를 조작 하기 전에 전환 합 니 다.데이터 베 이 스 를 조작 하기 전에 다음 과 같은 코드 를 추가 하면 됩 니 다.
DynamicDataSourceHolder.setRouteKey("dataSource2");
위 에서 소개 한 것 은 dao 층 에서 데이터 원본 을 전환 해 야 할 때 수 동 으로 데이터 원본 을 전환 하 는 코드 를 추가 하거나 AOP 방식 을 사용 할 수 있 습 니 다.설 정 된 데이터 원본 형식 을 모두 주석 라벨 로 설정 하고 dao 층 에서 데이터 원본 을 전환 하 는 방법 이나 클래스 에 주석 라벨 을 써 서 조작 성 이 더욱 강 합 니 다.
@DataSourceKey("dataSource1")
public interface TestEntityMapper extends MSSQLMapper<TestEntity> {
public void insertTest(TestEntity testEntity);
}
DataSourceKey 주석 코드 는 다음 과 같 습 니 다.
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSourceKey {
String value() default "";
}
주석 설정 이 끝 난 후에 데이터 원본 전환 을 실현 하 는 클래스 를 써 야 합 니 다.다음 과 같 습 니 다.
public class MultipleDataSourceExchange {
/**
* , @DataSource ,
*/
public void beforeDaoMethod(JoinPoint point) throws Exception {
Class<?> target = point.getTarget().getClass();
MethodSignature signature = (MethodSignature) point.getSignature();
// ,
for (Class<?> cls : target.getInterfaces()) {
resetDataSource(cls, signature.getMethod());
}
resetDataSource(target, signature.getMethod());
}
/**
*
*/
private void resetDataSource(Class<?> cls, Method method) {
try {
Class<?>[] types = method.getParameterTypes();
//
if (cls.isAnnotationPresent(DataSourceKey.class)) {
DataSourceKey source = cls.getAnnotation(DataSourceKey.class);
DynamicDataSourceHolder.setRouteKey(source.value());
}
//
Method m = cls.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DataSourceKey.class)) {
DataSourceKey source = m.getAnnotation(DataSourceKey.class);
DynamicDataSourceHolder.setRouteKey(source.value());
}
} catch (Exception e) {
System.out.println(cls + ":" + e.getMessage());
}
}
}
코드 를 다 쓴 후 xml 프로필 에 설정 을 추가 해 야 합 니 다.(부분 설정 만 표시)
<bean id="multipleDataSourceExchange" class="MultipleDataSourceExchange "/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="multipleDataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="insert*" propagation="NESTED" rollback-for="Exception"/>
<tx:method name="add*" propagation="NESTED" rollback-for="Exception"/>
...
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="service" expression="execution(* com.datasource..*.service.*.*(..))"/>
<!-- -->
<aop:advisor advice-ref="multipleDataSourceExchange" pointcut-ref="service" order="1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="service" order="2"/>
</aop:config>
AOP 방식 으로 다 중 데이터 원본 의 동적 전환 이 완료 되 었 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.