超强解决mybatis plus 多数据原问题,BaseMapper增强工具一样可用

前言

            在使用mybatis plus 时这个增强工具最大的贡献就是代码自动生成:(代码自动生成文章)https://blog.csdn.net/weixin_45863786/article/details/104544388(解决 not found mapper:https://blog.csdn.net/weixin_45863786/article/details/110954847),和BaseMapper增强工具,如果在某些业务情况下考虑跨数据库服务查询,怎样解决mybatis plus 多数据源问题,及使用多数据源无法使用BaseMapper增强工具解决方法,直接上代码。

一.application.properties多数据源配置

#多数据源配置
datasource.ev.driver-class-name = com.mysql.cj.jdbc.Driver
datasource.ev.url = jdbc:mysql://xx.xxx.xx.xx:6033/ev?useUnicode=true&characterEncoding=gbk&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&useSSL=false&jdbcCompliantTruncation=false
datasource.ev.username = xx
datasource.ev.password = xx

datasource.l2.driver-class-name = com.mysql.cj.jdbc.Driver
datasource.l2.url = jdbc:mysql://xx.xxx.xx.xx:3306/iov_cpsp?useUnicode=true&characterEncoding=gbk&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&jdbcCompliantTruncation=false
datasource.l2.username = xx
datasource.l2.password = xx

datasource.app.driver-class-name = com.mysql.cj.jdbc.Driver
datasource.app.url = jdbc:mysql://xx.xxx.xx.xx:3306/fleet?useUnicode=true&characterEncoding=gbk&zeroDateTimeBehavior=CONVERT_TO_NULL&serverTimezone=Asia/Shanghai&jdbcCompliantTruncation=false
datasource.app.username = xx
datasource.app.password = xx

二. 定义数据源枚举

package com.ly.mp.app.common.multiple.enums;

import lombok.AccessLevel;
        import lombok.AllArgsConstructor;
        import lombok.Getter;

/**
 * 定义数据源枚举
 * @author huangan
 * @date 2020/11/30 9:56
 */
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public enum DataSourceEnum {
    EV("ev"),
    L2("l2"),
    APP("app");
    private String value;
}

三. 定义数据源注解

package com.ly.mp.app.common.multiple.annotation;

import com.ly.mp.app.common.multiple.enums.DataSourceEnum;

import java.lang.annotation.*;

/**
 * 定义数据源注解
 * @author huangan
 * @date 2020/11/30 9:58
 */
@Inherited
@Target(value = {ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    DataSourceEnum value() default DataSourceEnum.EV;
}

 

四.多数据源

package com.ly.mp.app.common.multiple;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 多数据源
 * @author huangan
 * @date 2020/11/30 10:09
 */
public class MultipleDataSource  extends AbstractRoutingDataSource {
    private static final ThreadLocal contextHolder = new InheritableThreadLocal<>();

    @Override
    protected Object determineCurrentLookupKey() {
        return this.getDataSource();
    }

    /**
     * 设置数据源
     *
     * @param db
     */
    public static void setDataSource(String db) {
        contextHolder.set(db);
    }

    /**
     * 取得当前数据源
     *
     * @return
     */
    public static String getDataSource() {
        return contextHolder.get();
    }

    /**
     * 清除上下文数据
     */
    public static void clear() {
        contextHolder.remove();
    }
}

 

五. 数据aop切换

package com.ly.mp.app.common.multiple.aop;
import com.ly.mp.app.common.multiple.MultipleDataSource;
import com.ly.mp.app.common.multiple.annotation.DataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
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.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;

/**
 * 数据要aop切换
 * @author huangan
 * @date 2020/11/30 10:07
 */
@Component
@Slf4j
@Aspect
@Order(-1)
public class DataSourceAspect {

    @Pointcut("this(com.baomidou.mybatisplus.core.mapper.BaseMapper)")
    private void pointCut() { }

    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        Class c =  joinPoint.getTarget().getClass();
        //获取构造函数中的
        Class[] interfaces = c.getInterfaces();
        Arrays.stream(interfaces).forEach(
                x->{
                    if(x.isAnnotationPresent(DataSource.class)){
                        DataSource dataSourceKey = x.getAnnotation(DataSource.class);
                        MultipleDataSource.setDataSource(dataSourceKey.value().getValue());
                    }
                }
        );
    }

    @After("pointCut()")
    public void doAfter() {
        MultipleDataSource.clear();
    }
}

 

六.MybatisPlusConfig配置多数据源

package com.ly.mp.app.config;

import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.ly.mp.app.common.multiple.MultipleDataSource;
import com.ly.mp.app.common.multiple.enums.DataSourceEnum;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


/**
 * MybatisPlus配置类
 * @author huangan
 * @date 2020/11/16 17:36
 */
@Configuration
public class MybatisPlusConfig {

    /**
     * @description: 配置分页插件
     * @author: gradual
     * @param: []
     * @return: com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /**
     * @description: SQL执行效率插件
     * @author: gradual
     * @param: []
     * @return: com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor
     */
    @Bean
    public PerformanceInterceptor performanceInterceptor() {
        return new PerformanceInterceptor();
    }

    /**
     * 逻辑删除用,3.1.1之后的版本可不需要配置该bean,但项目这里用的是3.1.0的
     * @author David Hong
     * @return com.baomidou.mybatisplus.core.injector.ISqlInjector
     */
    @Bean
    public ISqlInjector sqlInjector() {
        return (ISqlInjector) new LogicSqlInjector();
    }

    @Bean(name = "l2")
    @ConfigurationProperties(prefix = "datasource.l2")
    public DataSource l2() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "app")
    @ConfigurationProperties(prefix = "datasource.app")
    public DataSource app() {
        return DruidDataSourceBuilder.create().build();
    }


    @Bean(name = "globalConfig")
    @Primary
    public GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        return globalConfig;
    }

    @Bean
    @Primary
    public DataSource multipleDataSource(@Qualifier("l2") DataSource l2,@Qualifier("app") DataSource app) {
        MultipleDataSource multipleDataSource = new MultipleDataSource();
        Map targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceEnum.L2.getValue(), l2);
        targetDataSources.put(DataSourceEnum.APP.getValue(), app);

        //添加数据源
        multipleDataSource.setTargetDataSources(targetDataSources);
        //设置默认数据源
        multipleDataSource.setDefaultTargetDataSource(app);
        return multipleDataSource;
    }

    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(multipleDataSource(l2(),app()));
        factoryBean.setGlobalConfig(globalConfig());
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 需要在这里指定xml文件的位置,不然自定义的sql会报Invalid bound statement异常
        factoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/*Mapper.xml"));
        // 导入mybatis配置 构造方法,解决动态数据源循环依赖问题
        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
        // 配置分页插件
        mybatisConfiguration.addInterceptor(new PaginationInterceptor());
        // 配置打印sql语句
        mybatisConfiguration.setLogImpl(StdOutImpl.class);
        factoryBean.setConfiguration(mybatisConfiguration);
        return factoryBean.getObject();
    }

  /*
    @Bean("sqlSessionFactory")
    @Primary
    public SqlSessionFactory dbSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource, GlobalConfig globalConfig) throws Exception {
        // MybatisSqlSessionFactoryBean
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setGlobalConfig(globalConfig());

        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 需要在这里指定xml文件的位置,不然自定义的sql会报Invalid bound statement异常
        factoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/*Mapper.xml"));

        // 导入mybatis配置 构造方法,解决动态数据源循环依赖问题
        MybatisConfiguration mybatisConfiguration = new MybatisConfiguration();
        // 配置分页插件
        mybatisConfiguration.addInterceptor(new PaginationInterceptor());
        // 配置打印sql语句
        mybatisConfiguration.setLogImpl(StdOutImpl.class);
        factoryBean.setConfiguration(mybatisConfiguration);

        return factoryBean.getObject();
    }*/
}

 

七.dao层注解自定义接口指名数据源

package com.ly.mp.app.mapper;

import com.ly.mp.app.common.multiple.annotation.DataSource;
import com.ly.mp.app.common.multiple.enums.DataSourceEnum;
import com.ly.mp.app.entity.po.TAppUserPassLogin;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * 

* 用户登录验证 Mapper 接口 *

* * @author huangan * @since 2020-12-07 */ @DataSource(DataSourceEnum.APP) public interface TAppUserPassLoginMapper extends BaseMapper { }

 

不管使用BaseMapper增强类还是自己手写sql都支持

 

 

 

你可能感兴趣的:(Mybatis,mybatis,plus,多数据源,BaseMapper,mybatis)