admin 发表于 2016-6-8 16:50

springMvc +hibernate 实现多数据源动态切换

一、实现目的   

      最近在做任务统计平台,对平台大体做一个介绍。两个平台,学科学习资源管理平台和学科教学资源管理平台,每个平台下有三科(外数语),另外加统一认证平台,七个项目也就是说有7个数据源。

       虽然说是两个平台,但只是业务逻辑稍微不同罢了,各个科目下的dao和service以及JOB其实都是可以统用的。以前各个定时统计任务都是分布在各个科目中的,导致一开始做的时候就要拷贝多份,特别是业务逻辑修改的时候特别头疼,各种拷贝,还得写一堆上线单。

       所以采用springMvc+hibernate+mysql+dubbo 实现的多数据源切换 统计平台,实现对dao和
service以及job层的统一调用,只需切换不同的数据源即可。dubbo这里只是做远程接口调用,暂且可以不用看。


二、实现方式

1、配置 applicationContext-datasource.xml
这里是简单的配置了2个数据源做实例,统一配置和学科学习数学科目的数据源。 <!-- 统一配置数据源 -->
    <bean id="dataSourceSSO" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          <property name="driverClassName" value="${jdbc.driverClassName}" />
          <property name="url" value="${jdbc.url_SSO}" />
          <property name="username" value="${jdbc.user}" />
          <property name="password" value="${jdbc.pass}" />
    </bean>
    <!-- 配置数学数据源 -->
    <bean id="dataSourceFmM" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
          <property name="driverClassName" value="${jdbc.driverClassName}" />
          <property name="url" value="${jdbc.url_Fm_M}" />
          <property name="username" value="${jdbc.user}" />
          <property name="password" value="${jdbc.pass}" />
    </bean>
    <bean id="multipleDataSource" class="com.acts.web.common.persistence.DynamicDataSource">
      <property name="defaultTargetDataSource" ref="dataSourceFmM"/>
      <property name="targetDataSources">
            <map>   
                <!-- 注意这里的value是和上面的DataSource的id对应,key要和下面的CustomerContextHolder中的常量对应 -->
                <entry value-ref="dataSourceSSO"key="SSODataSource"/>
                <entry value-ref="dataSourceFmM"key="MDataSourceFm"/>
            </map>   
      </property>
    </bean>
    <!-- Annotation 配置sessionFactory,配置数据库连接,注入hibernate数据库配置 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
      <property name="dataSource" ref="multipleDataSource"/>
      <property name="configLocation" value="classpath:hibernate.cfg.xml" />
      <property name="hibernateProperties">
            <props>
                <!-- 链接释放策略 on_close | after_transaction | after_statement | auto-->
                <prop key="hibernate.connection.release_mode">after_transaction</prop>
               <!--<prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop> -->
                <!--数据库批量查询最大数 -->
                <prop key="hibernate.jdbc.fetch_size">50</prop>
                <!--数据库批量更新、添加、删除操作最大数 -->
                <prop key="hibernate.jdbc.batch_size">50</prop>
            </props>
      </property>
    </bean>
    <!-- 统一配置AOP切面注入 直接切入dao层使用默认数据源-->
    <aop:config>
      <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor">
            <aop:pointcut id="daoSSO" expression="within(com.acts.web.modules.rmp.dao.AnalysisQuesSsoDao)" />
            <aop:before pointcut-ref="daoSSO" method="setdataSourceSSO" />
      </aop:aspect>
    </aop:config>

2、applicationContext.xml 数据库参数配置

<!-- 加載配置文件 -->
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="order" value="1"/>
      <property name="ignoreUnresolvablePlaceholders" value="true"/>
      <property name="locations">
      <list>
            <value>classpath:persistence-mysql.properties</value>
      </list>
      </property>
    </bean>


3、DatabaseContextHolder.java 多数据源
/**
* 多数据源
* 创建者    张志朋
* 创建时间    2016年5月26日
*
*/
public class DatabaseContextHolder {

    public final static String DATA_SOURCE_SSO = "SSODataSource";
    public final static String DATA_SOURCE_FM_MATH = "MDataSourceFm";
    public final static String DATA_SOURCE_FM_ENGLISH = "EDataSourceFm";
    public final static String DATA_SOURCE_FM_CHINESE = "LDataSourceFm";

    public final static String DATA_SOURCE_K12_MATH = "MDataSourceK12";
    public final static String DATA_SOURCE_K12_ENGLISH = "EDataSourceK12";
    public final static String DATA_SOURCE_K12_CHINESE = "LDataSourceK12";

    public final static String DATA_SOURCE_K12 = "K12DataSource";
    public final static String DATA_SOURCE_K12_ONLINE = "K12OnlineDataSource";

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

    public static void setCustomerType(String customerType) {
      contextHolder.set(customerType);
    }
    public static String getCustomerType() {
      return contextHolder.get();
    }

    public static void clearCustomerType() {
      contextHolder.remove();
    }
}
4、DynamicDataSource.java动态据源实现
/**
* 动态据源实现
* 创建者    张志朋
* 创建时间    2016年5月25日
*
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
      return DatabaseContextHolder.getCustomerType();   
    }
}5、DataSourceInterceptor.java 拦截器实现 注入
/**
* 拦截器实现 注入
* 创建者    张志朋
* 创建时间    2016年5月26日
*
*/
@Component
public class DataSourceInterceptor {
    public void setdataSourceSSO(JoinPoint jp) {
      DatabaseContextHolder.setCustomerType("SSODataSource");
    }
}
6、MultipleDataSourceServiceImplTest.java单元测试
@ContextConfiguration({ "classpath:applicationContext-datasource.xml",
    "classpath:applicationContext.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class MultipleDataSourceServiceImplTest {
    @Test
    public void testDao() {
      //数学科目 统计
      DatabaseContextHolder.setCustomerType(DatabaseContextHolder.DATA_SOURCE_FM_MATH);
      //英语科目 统计
      DatabaseContextHolder.setCustomerType(DatabaseContextHolder.DATA_SOURCE_FM_ENGLISH);
      //语文科目 统计
      DatabaseContextHolder.setCustomerType(DatabaseContextHolder.DATA_SOURCE_FM_CHINESE);
    }
}
运行单元测试,三科的统计 通过使用各自的数据源调用相同的JOB和service以及dao层实现任务统计。

admin 发表于 2016-6-8 17:58

如果 有不明白的地方 可以加群 或者我的QQ 获得帮助{:2_27:}
页: [1]
查看完整版本: springMvc +hibernate 实现多数据源动态切换