RT,数据库地址是动态的,如何才能从一个数据库切换到另一个数据库。数据库用的sqlserve。
另一个是动态数据库链接,不是写死的。
有没有可行性方案。

SSH情况下如何做到多数据库切换
- 写回答
- 好问题 0 提建议
- 关注问题
- 邀请回答
-
3条回答 默认 最新
- threenewbee 2018-04-18 02:13关注
1.首先需要一个 数据源类型的类。 public enum DBType { dataSource, frontDataSource; } 2.需要一个本地线程变量对象保存 数据源类型,这里使用的 是ThreadLocal,因为ThreadLocal 可以为每个线程单独创立一个新的副本变量。 public class ContextHolder { private static final ThreadLocal<Object> holder = new ThreadLocal<Object>(); public static void setDbType(DBType dbType) { holder.set(dbType); } public static DBType getDbType() { return (DBType) holder.get(); } public static void clearDbType() { holder.remove(); } } 3.需要一个动态数据源类用于代替之前的 dataSource bean,这个类需要继承AbstractRoutingDataSource,并且重写 determineCurrentLookupKey 方法,返回本地线程变量中保存的 数据源类型key。 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { DBType key = ContextHolder.getDbType();//获得当前数据源标识符 System.out.println("当前数据源 :" + key); return key; } } 4.需要一个拦截器,该拦截器可以根据实际情况进行配置,我这里是拦截 service根据方法名称去切换数据源,这里切记: a.@Order(1) 这个值必须有,因为数据源的获取也是通过拦截器中获取的,这个地方拦截器优先级必须高过数据源获取的拦截器。 b.@Aspect 注解 需要在application.xml 配置启用 <context:component-scan base-package="com"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <!-- -开启 aspect 注解使用 --> <aop:aspectj-autoproxy /> import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; /** * aop实现动态切换数据源 * */ @Aspect @Component @Order(1) public class DataSourceAopProxy { @Before("dataSourcePoint()") public void setDataSource(JoinPoint joinPoint){ Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); //此处进行切换数据源 根据业务条件 获取数据源id if(method.getName().contains("Front")){ ContextHolder.setDbType(DBType.frontDataSource); System.out.println("设置当前数据源 DBType.frontDataSource"); }else{ ContextHolder.setDbType(DBType.dataSource); System.out.println("设置当前数据源 DBType.dataSource"); } } @After("dataSourcePoint()") public void after(JoinPoint joinPoint){ System.out.println("清除 DB type!"); ContextHolder.clearDbType(); } //@Pointcut("execution(* com.dao.impl.*.*(..))") @Pointcut("execution(* com.service.impl.*.*(..))") private void dataSourcePoint(){ } } 5.需要配置两个数据源和上面的数据源类型对应,我这里${jdbc.url}是读取的属性文件,你们可以在这里直接写值 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="initialPoolSize" value="${connection_pools.initial_pool_size}" /> <property name="minPoolSize" value="${connection_pools.min_pool_size}" /> <property name="maxPoolSize" value="${connection_pools.max_pool_size}" /> <property name="maxIdleTime" value="${connection_pools.max_idle_time}" /> <property name="acquireIncrement" value="${connection_pools.acquire_increment}" /> <property name="checkoutTimeout" value="${connection_pools.checkout_timeout}" /> </bean> <bean id="frontDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${front.jdbc.driver}" /> <property name="jdbcUrl" value="${front.jdbc.url}" /> <property name="user" value="${front.jdbc.username}" /> <property name="password" value="${front.jdbc.password}" /> <property name="initialPoolSize" value="${connection_pools.initial_pool_size}" /> <property name="minPoolSize" value="${connection_pools.min_pool_size}" /> <property name="maxPoolSize" value="${connection_pools.max_pool_size}" /> <property name="maxIdleTime" value="${connection_pools.max_idle_time}" /> <property name="acquireIncrement" value="${connection_pools.acquire_increment}" /> <property name="checkoutTimeout" value="${connection_pools.checkout_timeout}" /> </bean> 6.需要 修改 bean为entityManagerFactory的配置,其中将dataSource属性配置为 mysqlDynamicDataSource,如下: <property name="dataSource" ref="mysqlDynamicDataSource" /> 7.最后一步,配置 bean mysqlDynamicDataSource,对应上一步。 a.此处bean中targetDataSources 为目标数据源,key-type 值为数据源类型类,也就是第一条那个枚举。 b.map 中的key 对应的是数据源类型中的 两个枚举值,value-ref 则是第五条 配置的两个bean。 c.defaultTargetDataSource 为默认的数据源类型,就是本地线程变量中值 为null而默认的数据源对象。 <bean id="mysqlDynamicDataSource" class="com.titanos.dynamic.DynamicDataSource"> <property name="targetDataSources"> <!-- 标识符类型 --> <map key-type="com.dynamic.DBType"> <entry key="dataSource" value-ref="dataSource"/> <entry key="frontDataSource" value-ref="frontDataSource"/> </map> </property> <property name="defaultTargetDataSource" ref="dataSource"/> </bean>
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报