欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

mybatis-plus的多租戶不同版本實(shí)現(xiàn)的兩種方式

 更新時(shí)間:2025年03月17日 09:34:22   作者:小洋芋大土豆  
本文主要介紹了mybatis-plus的多租戶不同版本實(shí)現(xiàn)的兩種方式,Mybatis Plus 3.4.0版本之后多租戶的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下

Mybatis plus 3.4.0后的拓展插件

在mybatis- plus 3.4.0 版本之后可以,官方提供了MybatisPlusInterceptor 拓展插件

該插件是核心插件,目前代理了 Executor#query 和 Executor#update 和 StatementHandler#prepare 方法

InnerInterceptor

我們提供的插件都將基于此接口來(lái)實(shí)現(xiàn)功能

目前已有的功能:

  • 自動(dòng)分頁(yè): PaginationInnerInterceptor
  • 多租戶: TenantLineInnerInterceptor
  • 動(dòng)態(tài)表名: DynamicTableNameInnerInterceptor
  • 樂(lè)觀鎖: OptimisticLockerInnerInterceptor
  • sql 性能規(guī)范: IllegalSQLInnerInterceptor
  • 防止全表更新與刪除: BlockAttackInnerInterceptor

注意:

使用多個(gè)功能需要注意順序關(guān)系,建議使用如下順序

  • 多租戶,動(dòng)態(tài)表名
  • 分頁(yè),樂(lè)觀鎖
  • sql 性能規(guī)范,防止全表更新與刪除

總結(jié): 對(duì) sql 進(jìn)行單次改造的優(yōu)先放入,不對(duì) sql 進(jìn)行改造的最后放入

如果是mybatis plus 3.4.0 之后的版本可以直接使用多租戶插件

官方示例:

package com.baomidou.mybatisplus.samples.tenant.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;

/**
 * @author miemie
 * @since 2018-08-10
 */
@Configuration
@MapperScan("com.baomidou.mybatisplus.samples.tenant.mapper")
public class MybatisPlusConfig {

    /**
     * 新多租戶插件配置,一緩和二緩遵循mybatis的規(guī)則,需要設(shè)置 MybatisConfiguration#useDeprecatedExecutor = false 避免緩存萬(wàn)一出現(xiàn)問(wèn)題
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                // 這里可以寫(xiě)自己系統(tǒng)的獲取租戶id的方法   比如下面自定義方法
                // return new LongValue(CurrentUserUtils.getTenantId());
                return new LongValue(1);
            }
            
            /**
             * 獲取租戶字段名
             * <p>
             * 默認(rèn)字段名叫: tenant_id
             *
             * @return 租戶字段名
             */
             @Override
            default String getTenantIdColumn() {
                // 如果該字段你不是固定的,請(qǐng)使用 SqlInjectionUtils.check 檢查安全性
                return "tenant_id";
            }
        
             /**
              * 根據(jù)表名判斷是否忽略拼接多租戶條件
              * <p>
              * 默認(rèn)都要進(jìn)行解析并拼接多租戶條件
              *
              * @param tableName 表名
              * @return 是否忽略, true:表示忽略,false:需要解析并拼接多租戶條件
              */
            @Override
            public boolean ignoreTable(String tableName) {
               String[] arr = new String[]{
                       "susCode",
                       "suName",
                       "suSex",
                       "suAge"
               };
               return ArrayUtil.contains(arr, tableName);
            }
        }));
        // 如果用了分頁(yè)插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
        // 用了分頁(yè)插件必須設(shè)置 MybatisConfiguration#useDeprecatedExecutor = false
//        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }

//    @Bean
//    public ConfigurationCustomizer configurationCustomizer() {
//        return configuration -> configuration.setUseDeprecatedExecutor(false);
//    }
}

Mybatis plus 3.4.0 之前版本的自定義實(shí)現(xiàn)

因?yàn)楸敬伍_(kāi)發(fā)的模塊需要與系統(tǒng)的老版本兼容,使用的版本為3.1.1則出現(xiàn)了不能夠使用官方自帶的增強(qiáng)插件,所以需要自己通過(guò)實(shí)現(xiàn)攔截器來(lái)達(dá)到類似效果。

寫(xiě)的過(guò)程可以借鑒分頁(yè)插件PaginationInterceptor

自定義Interceptor 繼承AbstractSqlPAserHandler(SQL 解析處理器) 實(shí)現(xiàn)Inteceptor(攔截器)

攔截時(shí)機(jī)與PaginationInterceptor 一樣,在StatementHandler的prepare 進(jìn)行處理 照搬即可

這個(gè) Interceptor 接口定義了三個(gè)方法:

  • intercept(Invocation invocation):這是攔截器的核心方法,它允許攔截器在執(zhí)行目標(biāo)方法之前或之后添加自定義邏輯。當(dāng)攔截器被激活時(shí),intercept 方法會(huì)被調(diào)用。攔截器可以通過(guò) Invocation 對(duì)象訪問(wèn)目標(biāo)方法的參數(shù)、目標(biāo)對(duì)象等信息,并且可以通過(guò)調(diào)用 invocation.proceed() 來(lái)繼續(xù)執(zhí)行目標(biāo)方法,或者在此之前/之后添加自定義邏輯。
  • plugin(Object target):這個(gè)方法用于包裝目標(biāo)對(duì)象,返回一個(gè)代理對(duì)象。攔截器通過(guò)調(diào)用此方法來(lái)生成一個(gè)目標(biāo)對(duì)象的代理,代理對(duì)象中包含了攔截器的邏輯。這樣,在調(diào)用目標(biāo)對(duì)象的方法時(shí),攔截器的邏輯就會(huì)被觸發(fā)。
  • setProperties(Properties properties):這個(gè)方法用于設(shè)置攔截器的屬性。攔截器可以通過(guò)這個(gè)方法接收外部傳入的配置參數(shù),以便在運(yùn)行時(shí)動(dòng)態(tài)調(diào)整其行為。

這三個(gè)方法結(jié)合起來(lái),允許開(kāi)發(fā)者在 MyBatis 中實(shí)現(xiàn)自定義的攔截器邏輯,例如添加日志記錄、權(quán)限控制、性能監(jiān)控等功能。

這里plugin()和setProperties()照搬即可

主要對(duì)intercept 進(jìn)行處理

package com.panpass.rebate.service.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
import com.panpass.rebate.service.utils.CurrentRebateUserUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.BaseStatementHandler;
import org.apache.ibatis.executor.statement.PreparedStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.junit.jupiter.api.Order;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;



/**
 * @Description:
 * @Author: potato
 * @Date: 2024/4/8  9:49
 */


@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
//@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DataScopeInterceptor  extends AbstractSqlParserHandler implements Interceptor {

    /**
     * 是否對(duì)xml中SQL 進(jìn)行多租戶增強(qiáng)
     *  false   不進(jìn)行SQL增強(qiáng)
     *  true    進(jìn)行SQL增強(qiáng)
     *  配置 可轉(zhuǎn)移到nacos 中
     */
    private boolean openIngore = true;

    /**
     * 可以指定某些特定的XML中的SQL的方法進(jìn)行手寫(xiě),不通過(guò)該攔截器增強(qiáng)
     */
    private List<String> ingoreList;


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();
        //確保只有攔截的目標(biāo)對(duì)象是 StatementHandler 類型時(shí)才執(zhí)行特定邏輯
        boolean flag = true;
        if (target instanceof StatementHandler) {
            StatementHandler statementHandler = (StatementHandler) target;
            StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(statementHandler, "delegate");

            // true 則需要SQL多租戶增強(qiáng)
            try {
                flag = isIngoreXML(invocation);
            } catch (Exception e) {
                log.info("StatementHandler 解析出現(xiàn)問(wèn)題,請(qǐng)注意查看"+e.getMessage());
//                e.printStackTrace();
            }
            if (flag) {
                // 獲取 BoundSql 對(duì)象,包含原始 SQL 語(yǔ)句
                BoundSql boundSql = statementHandler.getBoundSql();
                String originalSql = boundSql.getSql();
                String newSql = setEnvToStatement(originalSql);
                // 使用MetaObject對(duì)象將新的SQL語(yǔ)句設(shè)置到BoundSql對(duì)象中
                MetaObject metaObject = SystemMetaObject.forObject(boundSql);
                metaObject.setValue("sql", newSql);
            }

        }
        // 執(zhí)行SQL
        return invocation.proceed();
    }

    /**
     *
     *  根據(jù)xml名稱判斷是否需要進(jìn)行xml 中SQL解析   可以拓展
     *
     * @param invocation
     * @return  fasle = 不進(jìn)行SQL增強(qiáng)   true 進(jìn)行SQL增強(qiáng)
     */
    public boolean isIngoreXML(Invocation invocation){
        // 不開(kāi)啟增強(qiáng)直接返回false
        if(!openIngore){
            return  false;
        }
        // 存在多層代理,SystemMetaObject獲取不確定,  借鑒PaginationInterceptor 中獲取Target的方法來(lái)獲取
        StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
        // SQL 解析
//        this.sqlParser(metaObject);
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

//         ingoreList  為空,沒(méi)有設(shè)置需要忽略增強(qiáng)的方法名   模擬存在配置了忽略的方法
//         ingoreList =new ArrayList<>();
//         ingoreList.add("RebateFlowBulkMapper.flowList");
        if(CollectionUtil.isEmpty(ingoreList)){
            return true;
        }
        // Resource 示例 :   file [D:\bjzx\project\rebate\rebate-dao\target\classes\mapper\plan\PlanConfigMapper.xml]   xml路徑
        // id       示例 :   com.panpass.rebate.plan.persistent.mapper.PlanConfigMapper.getPageList
        // 確保Resource 來(lái)自xml,并且配置的存在忽略的方法名例如: PlanConfigMapper.getPageList,返回false  不進(jìn)行增強(qiáng)處理;
        for (String menthodName : ingoreList) {
            if (mappedStatement.getResource().contains("xml") && mappedStatement.getId().contains(menthodName)) {
                return false;
            }
        }

        return true;
    }

    public static void printFields(Object obj) {
        Class clazz = obj.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object fieldValue = null;
            try {
                fieldValue = field.get(obj);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            System.out.println(fieldName + ": " + fieldValue);
        }
    }

    private String setEnvToStatement(String originalSql) {
        net.sf.jsqlparser.statement.Statement statement;
        try {
            statement = CCJSqlParserUtil.parse(originalSql);
        } catch (JSQLParserException e) {
            throw new RuntimeException("EnvironmentVariableInterceptor::SQL語(yǔ)句解析異常:"+originalSql);
        }

        if (statement instanceof Select) {
            //TODO需要遞歸處理
            Select select = (Select) statement;
            PlainSelect selectBody = (PlainSelect) select.getSelectBody();
            // 遞歸處理子查詢
            processSubQuery(selectBody);

            return select.toString();
        }
//        else if (statement instanceof Insert) {
//            Insert insert = (Insert) statement;
//            setEnvToInsert(insert);
//
//            return insert.toString();
//        } else if (statement instanceof Update) {
//            Update update = (Update) statement;
//            Expression newWhereExpression = setEnvToWhereExpression(update.getWhere(),null);
//            update.setWhere(newWhereExpression);
//
//            return update.toString();
//        } else if (statement instanceof Delete) {
//            Delete delete = (Delete) statement;
//            Expression newWhereExpression = setEnvToWhereExpression(delete.getWhere(),null);
//            delete.setWhere(newWhereExpression);
//
//            return delete.toString();
//        }
        return originalSql;
    }

    private  void processSubQuery(PlainSelect selectBody ) {

            if(selectBody == null){
                return;
            }
        if (selectBody.getFromItem() instanceof Table) {
            Expression newWhereExpression;
            if (selectBody.getJoins() == null || selectBody.getJoins().isEmpty()) {
                newWhereExpression = setEnvToWhereExpression(selectBody.getWhere(), null);
            } else {
                newWhereExpression = multipleTableJoinWhereExpression(selectBody);
            }
            selectBody.setWhere(newWhereExpression);
        } else {
            // 處理子查詢
            SelectBody subSelectBody = ((SubSelect) selectBody.getFromItem()).getSelectBody();
            processSubQuery((PlainSelect) subSelectBody);
//            selectBody.setFromItem((FromItem) processSubQuery((PlainSelect) subSelectBody));
        }
//        return selectBody;
    }

    //非遞查詢
    private  String setEnvToStatement2(String originalSql) {
        net.sf.jsqlparser.statement.Statement statement;
        try {
            statement = CCJSqlParserUtil.parse(originalSql);
        } catch (JSQLParserException e) {
            throw new RuntimeException("EnvironmentVariableInterceptor::SQL語(yǔ)句解析異常:"+originalSql);
        }
        if (statement instanceof Select) {
            Select select = (Select) statement;
            PlainSelect selectBody = (PlainSelect) select.getSelectBody();
            if (selectBody.getFromItem() instanceof Table) {
                Expression newWhereExpression;
                if (selectBody.getJoins() == null || selectBody.getJoins().isEmpty()) {
                    newWhereExpression = setEnvToWhereExpression(selectBody.getWhere(), null);
                } else {
                    // 如果是多表關(guān)聯(lián)查詢,在關(guān)聯(lián)查詢中新增每個(gè)表的環(huán)境變量條件
                    newWhereExpression = multipleTableJoinWhereExpression(selectBody);
                }
                // 將新的where設(shè)置到Select中
                selectBody.setWhere(newWhereExpression);
            } else if (selectBody.getFromItem() instanceof SubSelect) {
                // 如果是子查詢,在子查詢中新增環(huán)境變量條件
                // 當(dāng)前方法只能處理單層子查詢,如果有多層級(jí)的子查詢的場(chǎng)景需要通過(guò)遞歸設(shè)置環(huán)境變量
                SubSelect subSelect = (SubSelect) selectBody.getFromItem();
                PlainSelect subSelectBody = (PlainSelect) subSelect.getSelectBody();
                Expression newWhereExpression = setEnvToWhereExpression(subSelectBody.getWhere(), null);
                subSelectBody.setWhere(newWhereExpression);
            }

            // 獲得修改后的語(yǔ)句
            return select.toString();
        } else if (statement instanceof Insert) {
            Insert insert = (Insert) statement;
            setEnvToInsert(insert);

            return insert.toString();
        } else if (statement instanceof Update) {
            Update update = (Update) statement;
            Expression newWhereExpression = setEnvToWhereExpression(update.getWhere(),null);
            // 將新的where設(shè)置到Update中
            update.setWhere(newWhereExpression);

            return update.toString();
        } else if (statement instanceof Delete) {
            Delete delete = (Delete) statement;
            Expression newWhereExpression = setEnvToWhereExpression(delete.getWhere(),null);
            // 將新的where設(shè)置到delete中
            delete.setWhere(newWhereExpression);

            return delete.toString();
        }
        return originalSql;
    }

    /**
     * 將需要隔離的字段加入到SQL的Where語(yǔ)法樹(shù)中
     * @param whereExpression SQL的Where語(yǔ)法樹(shù)
     * @param alias 表別名
     * @return 新的SQL Where語(yǔ)法樹(shù)
     */
    private Expression setEnvToWhereExpression(Expression whereExpression, String alias) {
        // 添加SQL語(yǔ)法樹(shù)的一個(gè)where分支,并添加環(huán)境變量條件

        EqualsTo envEquals = new EqualsTo();
        envEquals.setLeftExpression(new Column(StringUtils.isNotBlank(alias) ? String.format("%s.tenant_id", alias) : "tenant_id"));
        envEquals.setRightExpression(new LongValue(CurrentRebateUserUtil.getTenantId() == null ? 1 :CurrentRebateUserUtil.getTenantId()));
        if (whereExpression == null){
            return envEquals;
        } else {
            AndExpression andExpression = new AndExpression(whereExpression,envEquals);
            // 將新的where條件加入到原where條件的右分支樹(shù)
            andExpression.setRightExpression(envEquals);
            andExpression.setLeftExpression(whereExpression);
            return andExpression;
        }
    }

    /**
     * 多表關(guān)聯(lián)查詢時(shí),給關(guān)聯(lián)的所有表加入環(huán)境隔離條件
     * @param selectBody select語(yǔ)法樹(shù)
     * @return 新的SQL Where語(yǔ)法樹(shù)
     */
    private Expression multipleTableJoinWhereExpression(PlainSelect selectBody){
        Table mainTable = (Table) selectBody.getFromItem();
        String mainTableAlias = mainTable.getAlias().getName();
        // 將 t1.tenant_id = tenant_id 的條件添加到where中
        Expression newWhereExpression = setEnvToWhereExpression(selectBody.getWhere(), mainTableAlias);
        List<Join> joins = selectBody.getJoins();
        for (Join join : joins) {
            FromItem joinRightItem = join.getRightItem();
            if (joinRightItem instanceof Table) {
                Table joinTable = (Table) joinRightItem;
                String joinTableAlias = joinTable.getAlias().getName();
                // 將每一個(gè)join的 tx.env = ENV 的條件添加到where中
                newWhereExpression = setEnvToWhereExpression(newWhereExpression, joinTableAlias);
            }
        }
        return newWhereExpression;
    }

    /**
     * 新增數(shù)據(jù)時(shí),插入tenant_id字段
     * @param insert Insert 語(yǔ)法樹(shù)
     */
    private void setEnvToInsert(Insert insert) {
        // 添加tenant_id列
        List<Column> columns = insert.getColumns();
        for (Column column : columns) {
            //若存在,不進(jìn)行處理
            if (column.getColumnName().equals("tenant_id")) {
                return;
            }
        }
        columns.add(new Column("tenant_id"));
        // values中添加環(huán)境變量值

        // 獲取插入值列表
        ItemsList itemsList = insert.getItemsList();
        if(itemsList instanceof MultiExpressionList ){
            List<ExpressionList> exprList = ((MultiExpressionList) itemsList).getExprList();
            for (ExpressionList expressionList : exprList) {
                expressionList.getExpressions().add(new LongValue(CurrentRebateUserUtil.getTenantId() == null ? 1 :CurrentRebateUserUtil.getTenantId()));
            }
        } else if (itemsList instanceof SubSelect) {
            // 處理子查詢
            log.info("子查詢插入語(yǔ)句業(yè)務(wù)");
        }

    }

    //測(cè)試邏輯使用的
    public static void main(String[] args) throws JSQLParserException {

        String slectSql = "select * from (select id from (select 1 from table3 where id =2))";
//        String s = setEnvToStatement(slectSql);

        String sql = "INSERT INTO my_table (column1, column2) VALUES (value1, value2), (value3, value4)";

        try {
            // 解析 INSERT 語(yǔ)句
            Statement statement = CCJSqlParserUtil.parse(sql);

            // 判斷是否是 INSERT 語(yǔ)句
            if (statement instanceof Insert) {
                Insert insert = (Insert) statement;
                List<Column> columns = insert.getColumns();

                columns.add(new Column("tenant_id"));
                // 獲取插入值列表
                ItemsList itemsList = insert.getItemsList();
                if(itemsList instanceof MultiExpressionList ){
                    itemsList =(MultiExpressionList)itemsList;
                    List<ExpressionList> exprList = ((MultiExpressionList) itemsList).getExprList();
                    for (ExpressionList expressionList : exprList) {
                        expressionList.getExpressions().add(new LongValue(CurrentRebateUserUtil.getTenantId() == null ? 1 :CurrentRebateUserUtil.getTenantId()));
                    }
                } else if (itemsList instanceof SubSelect) {
                    // 處理子查詢
                    log.info("子查詢插入語(yǔ)句使用");
                }
            }

        } catch (JSQLParserException e) {
            e.printStackTrace();
        }
    }




    /**
     * 生成攔截對(duì)象的代理
     *
     * @param target 目標(biāo)對(duì)象
     * @return 代理對(duì)象
     */
    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    /**
     * mybatis配置的屬性
     *
     * @param properties mybatis配置的屬性
     */
    @Override
    public void setProperties(Properties properties) {

    }

}

自對(duì)其邏輯進(jìn)行修改適配自己系統(tǒng)項(xiàng)目,實(shí)現(xiàn)了遞歸支持多級(jí)子查詢,對(duì)部分xml,方法級(jí)別 的SQL進(jìn)行忽略增強(qiáng)。

注冊(cè)攔截器:

package com.panpass.rebate.service.config;


import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @Description:
 * @Author: potato
 * @Date: 2024/4/3  13:49
 */

@Configuration
public class MyBatisConfig {





    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    // 只執(zhí)行一次
    @PostConstruct
    public void addDefaultTimeInterceptor() {
        /**
         * Mybatis攔截器可以使用@Component注解也可以在這里進(jìn)行配置
         * 在這里配置可以控制攔截器的執(zhí)行順序,所以注意去掉@Component注解
         */
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
            List<Interceptor> interceptors = configuration.getInterceptors();
            // 最后添加的會(huì)更早執(zhí)行
            
            configuration.addInterceptor(new PaginationInterceptor());
            configuration.addInterceptor(new DataScopeInterceptor());
        }
    }

}

攔截器不用@Component 注解,否則會(huì)被自動(dòng)配置掃描進(jìn)攔截,導(dǎo)致存在多個(gè)攔截器,

查看項(xiàng)目攔截器順序可以在InterceptorChain對(duì)象查看

或者org.apache.ibatis.session.Configuration 對(duì)象中的 interceptorChain 對(duì)象

到此這篇關(guān)于mybatis-plus的多租戶不同版本實(shí)現(xiàn)的兩種方式的文章就介紹到這了,更多相關(guān)mybatis-plus多租戶不同版本內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解基于MVC的數(shù)據(jù)查詢模塊進(jìn)行模糊查詢

    詳解基于MVC的數(shù)據(jù)查詢模塊進(jìn)行模糊查詢

    這篇文章主要介紹了Java基于MVC的數(shù)據(jù)查詢模塊進(jìn)行模糊查詢,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 詳解Spring AOP 實(shí)現(xiàn)主從讀寫(xiě)分離

    詳解Spring AOP 實(shí)現(xiàn)主從讀寫(xiě)分離

    本篇文章主要介紹了Spring AOP 實(shí)現(xiàn)主從讀寫(xiě)分離,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • SpringBoot實(shí)現(xiàn)登錄攔截器超詳細(xì)教程分享

    SpringBoot實(shí)現(xiàn)登錄攔截器超詳細(xì)教程分享

    對(duì)于管理系統(tǒng)或其他需要用戶登錄的系統(tǒng),登錄驗(yàn)證都是必不可少的環(huán)節(jié),尤其在?SpringBoot?開(kāi)發(fā)的項(xiàng)目中。本文為大家準(zhǔn)備了超詳細(xì)的SpringBoot實(shí)現(xiàn)登錄攔截器方法,快收藏一波吧
    2023-02-02
  • SpringBoot整合Mybatis-plus關(guān)鍵詞模糊查詢結(jié)果為空

    SpringBoot整合Mybatis-plus關(guān)鍵詞模糊查詢結(jié)果為空

    SpringBoot整合Mybatis-plus使用關(guān)鍵詞模糊查詢的時(shí)候,數(shù)據(jù)庫(kù)中有數(shù)據(jù),但是無(wú)法查找出來(lái),本文就來(lái)介紹一下SpringBoot整合Mybatis-plus關(guān)鍵詞模糊查詢結(jié)果為空的解決方法
    2025-04-04
  • java?spring?mvc處理器映射器介紹

    java?spring?mvc處理器映射器介紹

    這篇文章主要介紹了java?spring?mvc處理器映射器,文章圍繞equestMapping解析映射介紹展開(kāi)源碼內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • IDEA的Mybatis Log Plugin插件配置和使用詳解

    IDEA的Mybatis Log Plugin插件配置和使用詳解

    這篇文章主要介紹了IDEA的Mybatis Log Plugin插件配置和使用,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • springboot文件虛擬路徑映射方式

    springboot文件虛擬路徑映射方式

    這篇文章主要介紹了springboot文件虛擬路徑映射方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • RocketMQ?ConsumeQueue與IndexFile實(shí)時(shí)更新機(jī)制源碼解析

    RocketMQ?ConsumeQueue與IndexFile實(shí)時(shí)更新機(jī)制源碼解析

    這篇文章主要為大家介紹了RocketMQ?ConsumeQueue與IndexFile實(shí)時(shí)更新機(jī)制源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 將項(xiàng)目上傳到Maven中央倉(cāng)庫(kù)(2023最新版)

    將項(xiàng)目上傳到Maven中央倉(cāng)庫(kù)(2023最新版)

    本文主要介紹了將項(xiàng)目上傳到Maven中央倉(cāng)庫(kù)(2023最新版),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • Java實(shí)現(xiàn)聯(lián)系人管理系統(tǒng)

    Java實(shí)現(xiàn)聯(lián)系人管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)聯(lián)系人管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評(píng)論