mybatis springboot多数据源,根据使用的数据库不同,执行不同的sql语句

发布时间 2023-08-25 11:45:44作者: 似水了流年

springboot 多数据源配置就不说了,百度太多的用例,

这里只说下在多数据源下切换执行sql逻辑

1.xml sql嵌套,通过<if>标签来判断,用的是mybatis自己sql动态拼接的逻辑(不推荐,数据源多或者sql大的时候不方便)

 

2. mybatis 插件接口拦截sql进行替换,该方法不仅可以实现数据源执行sql的切换,还可以实现其他场景,而却sql片段也是独立的

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;
import uz.sinow.datasource.dynamic.DynamicDataSourceConfiguration;
import uz.sinow.datasource.dynamic.ShardingContextHolder;

/**
 *
 * 多数据源sql方言切换拦截器,
 * 通过拦截方式替换执行sql来实现sql的切换,databaseId未查到正确的注入方式,这个通过mybatis的MappedStatement对象的
 * 替换来实现
 * 替换规则,原MappedStatement的id加上‘_’+数据源切库标识
 */
@Component("DynmicDatabaseSql")
@Intercepts({
        @Signature(type= Executor.class, method="query", args={MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        @Signature(type= Executor.class, method="query", args={MappedStatement.class,Object.class,RowBounds.class, ResultHandler.class})
})
public class DynamicMappedStatementChooseInterceptor implements Interceptor {

    private String base;

    public DynamicMappedStatementChooseInterceptor(DynamicDataSourceConfiguration dynamicDataSourceConfiguration) {
        this.base = dynamicDataSourceConfiguration.getBase();
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //取出当前数据源的DSName
        String ds = ShardingContextHolder.getDS();
        //如果是基本数据源(未指定表示用的是基本数据源)执行默认的方法对应的sql
        if (ds == null || ds.trim().length() == 0 || ds.equals(base))
            return invocation.proceed();
        //取出当前要执行的sql
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        //查看是否有要替换的方言,有就替换,没有就还用默认的
        Configuration configuration = mappedStatement.getConfiguration();
        MappedStatement mappedStatement1 = configuration.getMappedStatement(mappedStatement.getId() + "_" + ds);
        if(mappedStatement1!=null)
            args[0] = mappedStatement1;
        return invocation.proceed();
    }
}
    <select id="codeType_db" resultType="java.lang.String" >
        select 1
    </select>

    <select id="codeType" resultType="java.lang.String">
        select 1
    </select>