mybatis/mybatis plus установить глобальные параметры/глобальные переменные/глобальные атрибуты/установить глобальные параметры вручную

1. Описание проблемы

Иногда в процессе использования mybatis/mybatis plus вам нужно использовать некоторые глобальные переменные для простоты обслуживания, такие как префикс имени таблицы, использовать унифицированный префикс таблицы для всего проекта, определить его как переменную и использовать непосредственно в xml, что экономит много работы.

Два, решение

Есть 2 способа сделать это:

метод первый

mybatis/mybatis plus по умолчанию поддерживает глобальные переменные, которые можно настроить следующим образом:

конфигурация mybatis-plus:

mybatis-plus:
  typeAliasesPackage: com.xxx.entity
  mapperLocations: classpath*:mapper/*.xml
  configurationProperties:
    tablePrefix: test_ # 自定义sql中表名带前缀

Конфигурация Mybatis:

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.xxx
  configuration:
    variables:
      tablePrefix: test_ 

В xml вы можете получить его напрямую через ${}

    <select id="selectListAll" resultType="com.xxx.User">
        select * from ${
    
    tablePrefix}main_user
    </select>

Одна проблема с этим методом заключается в том, что после запуска проекта сначала будут заменены определенные глобальные переменные, а место замены находится в

Метод parseBody в методе построения org.apache.ibatis.parsing.XNode
вставьте сюда описание изображения
заменит заполнитель ${tablePrefix}
вставьте сюда описание изображения
Другими словами, этот метод работает после запуска проекта.

Способ второй

Вышеупомянутый метод полностью заменяется после запуска, и иногда нам нужно динамически передавать фиксированные переменные во время запущенного процесса.В настоящее время вышеуказанный метод неприменим.Есть ли способ динамически установить глобальный параметр среды выполнения? Да, посмотрите на исходный код, и вы обнаружите, что при анализе динамического SQL DynamicContext будет вызываться в методе org.apache.ibatis.scripting.xmltags.TextSqlNode.BindingTokenParser#handleToken, если мы устанавливаем параметры перед выполнением связанные операции Ручное введение глобальных параметров может быть достигнуто,

вставьте сюда описание изображения
Как? В mybatis предусмотрен механизм плагинов, и это можно сделать с его помощью.Посмотрите на документ плагина mybatis, он может перехватывать некоторые операции, разве это не тот результат, который мы хотим, мы можем настроить плагин- в, полный код выглядит следующим образом:

import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.core.toolkit.TableNameParser;
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.scripting.xmltags.DynamicContext;
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
import org.apache.ibatis.scripting.xmltags.SqlNode;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

/**
 * @version: V1.0
 * @author: mszf
 * @date: 2022-02-08 23:08
 * @description: 全局参数注入
 */
@Slf4j
@Intercepts({
    
     @Signature(method = "update", args = {
    
     MappedStatement.class, Object.class }, type = Executor.class),
        @Signature(method = "query", args = {
    
     MappedStatement.class, Object.class, RowBounds.class,
                ResultHandler.class }, type = Executor.class) })
public class GlobalParametersInterceptor implements Interceptor {
    
    

    private Set<Integer> sourceStorage = new HashSet<Integer>();


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
    
    
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        SqlSource sqlSource = mappedStatement.getSqlSource();
        // 只拦截动态sql
        if (sqlSource instanceof DynamicSqlSource) {
    
    
            // 获取到sqlNode对象
            Field field = DynamicSqlSource.class.getDeclaredField("rootSqlNode");
            field.setAccessible(true);
            SqlNode sqlnode = (SqlNode) field.get(sqlSource);
            if (!sourceStorage.contains(sqlSource.hashCode())) {
    
    
                // 获取动态代理对象
                SqlNode proxyNode = proxyNode(sqlnode);
                field.set(sqlSource, proxyNode);
                sourceStorage.add(sqlSource.hashCode());
            }
        }
        return invocation.proceed();
    }

    private SqlNode proxyNode(SqlNode sqlnode) {
    
    
        SqlNode proxyNode = (SqlNode) Proxy.newProxyInstance(sqlnode.getClass().getClassLoader(),
                new Class[]{
    
    SqlNode.class}, new SqlNodeInvocationHandler(sqlnode));
        return proxyNode;
    }

    @Override
    public Object plugin(Object target) {
    
    
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    
    
    
    }

    private class SqlNodeInvocationHandler implements InvocationHandler {
    
    

        private final SqlNode target;

        public SqlNodeInvocationHandler(SqlNode target) {
    
    
            super();
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
            Setting setting = SettingUtils.readInstallSetting();
            DynamicContext context = (DynamicContext) args[0];
            //手动添加
            context.getBindings().put("tablePrefix","xxxxxx");
            return method.invoke(target, args);
        }

    }
}

Просто введите его в весну

    @Bean
    public GlobalParametersInterceptor globalParametersInterceptor(){
    
    
        return new GlobalParametersInterceptor();
    }

Guess you like

Origin blog.csdn.net/mashangzhifu/article/details/122845644