数据源的无缝切换

随着业务的发展,用户量的增大,单表单库已经满足不了我们的业务需求,因此需要分库分表,但是随之带来的问题是当我们需要从库中捞取某些数据的时候,经常需要在多个数据库来回切换,如何做到无缝切换,这里主要通过配置数据源,自定义注解和aop技术来解决。主要包含以下4步:

1、切换数据源

例如我们有两个数据源,一个是ds0,一个是ds1,我们可以通过如下方式配置一个动态数据源。我们只需要自定义一个类继承AbstractRoutingDatasource,实现determineCurrentLookupKey方法,这个方法可以决定我们每次使用的数据源。contextHolder则是一个线程局部变量,保证线程的安全。也就是只要每次在准备切换数据库的时候,通过contextHolder.setDatabaseName就可以切换数据源了。

/**
 * 功能:数据库切换工具类
 * 版本:1.0
 * 日期:2016/12/2 13:44
 * 作者:屠苏
 */
public class DataSourceContextHolder {
    // 线程局部变量,用于保存保存数据库的名称
    private static final ThreadLocal<String> contextHolder = new InheritableThreadLocal<String>();

    public static void setDataBaseName(String dataBaseName) {
        contextHolder.set(dataBaseName);
    }

    public static String getDataBaseName() {
        return contextHolder.get();
    }

    public static void clearDataBaseName() {
        contextHolder.remove();
    }
}
/**
 * 功能:动态数据源
 * 版本:1.0
 * 日期:2016/12/2 13:49
 * 作者:屠苏
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    // 返回数据源的key
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataBaseName();
    }
}
<!--配置动态数据源-->
<bean id="dataSource" class="com.netease.payment.util.datasource.DynamicDataSource">
    <property name="targetDataSources">
        <map key-type="java.lang.String">
            <entry key="ds0" value-ref="dataSource0"/>
            <entry key="ds1" value-ref="dataSource1"/>
        </map>
    </property>
    <property name="defaultTargetDataSource" ref="dataSource0"/>
</bean>

2、自定义注解

首先做一个自定义注解,然后每次在需要切数据源的方法上加上@Datasource("xx")就可以了。

/**
 * 描述: 自定义数据源注解
 * 版本号: 1.0
 * 日期: 2017/2/21 11:49
 * 作者: 屠苏
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Datasource {
    String value() default "ds0";
}

3、Aop

首先定义一个切入点,对所有存在@Datasource的注释的方法进行切面,然后获取签名方法,获取方法上的注释,替换数据源。

package com.elin4it.ssm.aop;

import com.elin4it.ssm.annotation.Datasource;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * 功能:切换数据源aop
 * 版本:1.0
 * 日期:2016/12/29 14:18
 * 作者:屠苏
 */
@Aspect
@Component
public class DsAop {

    /**
     * 第一个 * 代表所有的返回值类型
     * 第二个 * 代表所有的类
     * 第三个 * 代表类所有方法
     * 最后一个 .. 代表所有的参数
     */
    @Pointcut("@annotation(com.elin4it.ssm.annotation.Datasource)")
    private void anyMethod(){}//定义一个切入点

    @Before("anyMethod()")
    public void before(JoinPoint joinPoint){
        Object target = joinPoint.getTarget();
        Class<?> classObj = target.getClass();

        // 获取连接点的签名方法对象
        Signature signature = joinPoint.getSignature();
        System.out.println("signature method=" + signature.getName());

        // 方法名
        String methodName = joinPoint.getSignature().getName();

        // 方法参数类型
        Class<?>[] paraClasses = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();

        try {
            Method method = classObj.getMethod(methodName, paraClasses);

            if(method != null && method.isAnnotationPresent(Datasource.class)) {
                Datasource dataSource = method.getAnnotation(Datasource.class);

                /**
                 * 切换数据源 !!!!!!!
                 */
                DataSourceContextHolder.setDataBaseName(dataSource.value());

                System.out.println("value=" + dataSource.value());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @After("anyMethod()")
    public void after(){}

    @AfterThrowing("anyMethod()")
    public void exception(){}

    @Around("anyMethod()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        Object object = pjp.proceed();//执行该方法
        return object;
    }
}

4、调用切换数据源的方法

@Datasource("ds1")
public void testSwitchDS() {
    System.out.println("调用testSwitchDS方法!");
}

转载于:https://my.oschina.net/u/3203060/blog/842939

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据集成标准规范文档定义了数据集成的标准和规范,旨在提供一种统一的方法来管理和集成不同数据之间的数据。这些标准和规范有助于解决异构环境数据的问题,包括不同时间期间、不同公司、不同工具和不同平台导致的数据冗余、垃圾数据数据一致性问题。 数据集成的好处在于它可以通过提供统一的表示、存储和管理方式,将各种异构数据进行集中和集成。集成的目的是维护数据整体上的数据一致性,并提高信息共享和利用效率。 数据集成标准规范文档还涉及一些关键问题,包括集成范围问题、全局模式问题、模式映射问题和数据动态集成问题。集成范围问题涉及权限、数据所有权等方面的限制;全局模式问题涉及如何合并不同数据数据;模式映射问题涉及解决冲突的规则;数据动态集成问题涉及动态变化的数据集成。 在数据集成过程中,基于XML的异构数据集成起着重要的作用。XML可以提供一种统一的数据模式来描述不同数据中的数据,并屏蔽它们的平台和数据结构的异构性,从而实现数据的无缝集成。同时,XML还可以用于数据转换、数据迁移和数据抽取等方面的处理。 综上所述,数据集成标准规范文档是一个为解决异构环境下的数据集成问题而制定的文档。它定义了数据集成的标准和规范,包括统一的数据表示、存储和管理方式,并涉及解决集成范围、全局模式、模式映射和数据动态集成等关键问题。同时,文档也强调了基于XML的异构数据集成在整个数据集成过程中的重要作用[1]。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值