Spring MVC 多数据源实践

一世执手 提交于 2020-04-27 03:03:58

数据库情况:A数据库(oracle)+B数据库(Mysql)

一、applicationContext.xml配置

   

<!-- A库 -->
    <bean id="dataSourceA" class="com.mchange.v2.c3p0.ComboPooledDataSource"    destroy-method="close">
        …………
    </bean>
    
    <!-- B库 -->
    <bean id="dataSourceB" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        …………
    </bean>
    
    <!-- 动态数据源 -->
    <bean id="dynamicDataSource" class="edu.portal.demo.dataSource.DynamicDataSource">
        <property name="targetDataSources">  
            <map key-type="java.lang.String">  
                <entry key="dbA" value-ref="dataSourceA" />  
                <entry key="dbB" value-ref="dataSourceB" />  
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="dataSourceA" /> 
    </bean>
        
    
    <bean id="jdbcTemplate"
        class="org.springframework.jdbc.core.JdbcTemplate" abstract="false"
        lazy-init="true" autowire="default">
        <property name="dataSource">
            <ref bean="dynamicDataSource" />
        </property>
    </bean>

二、创建DynamicDataSource并继承AbstractRoutingDataSource

public class DynamicDataSource extends AbstractRoutingDataSource{
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  

    public static final String DB_A="dbA";//该字符串与XML配置中的

    public static final String DB_B="dbB";
    /* (non-Javadoc)
     * @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return contextHolder.getCustomerType();
    }
      
    public static void setCustomerType(String customerType) {  
        contextHolder.set(customerType);  
    }  
  
    public static String getCustomerType() {  
        return contextHolder.get();  
    }  
  
    public static void clearCustomerType() {  
        contextHolder.remove();  
    }  
}

三、创建目标数据源AOP,这里切点就只是针对dbAServiceBean所有方法,本质就是在dbAServiceBean的方法执行前进行数据源切换。需要要使用另外一个库,就再加一个就OK了。

@Service
@Aspect
public class AspectDbADataSource {
    //这里就是拦截条件,只要使用这edu.portal.demo.dbAServiceBean这个类,就会切换到dbA
    public static final String POINTCUT = "execution(* edu.portal.demo.dbAServiceBean.*(..))";
    
    @Before(POINTCUT)  //在edu.portal.demo.dbAServiceBean方法执行之前切换
    public void changeDataSource() {  
        DynamicDataSource.setCustomerType(DynamicDataSource.DB_A);
    } 

}

四、实现dbAServiceBean对数据库的操作。

@Service
public class dbAServiceBean{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public void demo(){}
}


经过以上配置,把使用dbA数据库的方法写在一起,使用dbB数据库的(这里不举例)方法写在一起。

这样就可以不用管当前用的是什么库,只要在对应的ServiceBean里操作就会自动切换到对应的库,这方便。


由于缺乏对Spring整体的学习,都是临时抱佛脚,以下几篇文章对我的帮助不少:

一步一步学习spring(六)——注解方式实现AOP的例子

http://my.oschina.net/004/blog/367566

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!