背景:

  • 项目中需要根据企业分对应的数据库,所以要动态根据企业的标识去操作对应的数据库

思路:

  • mybatis plus 动态表名,但是有个缺点就是只会在项目启动是注入bean对象时调用一次,不像拦截器那样每次调用,所以放弃了;(其实简单的根据日期什么的切换数据表,直接用mp的这种实现更加简单)
  • 使用mybatis的拦截器

Example:

package com.huawen.framework.interceptor;

import cn.hutool.core.util.ObjectUtil;
import com.huawen.common.enums.CompanyEnum;
import com.huawen.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.springframework.stereotype.Component;

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

/**
 * @author:kyrie
 * @date:2022/12/7 9:48
 * @Description: 添加数据库前缀 拦截器
 **/
@Slf4j
// 注入到spring中托管
@Component
// @Intercepts表示是拦截器
// @Signature声明要拦截的接口、方法以及对应的参数列表
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class AddDbPrefixInterceptor implements Interceptor {
    /**
     * 拦截方法
     *
     * @param invocation 调用
     * @return obj
     * @throws Throwable 异常
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        log.info("执行intercept方法:{}", invocation.toString());
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        // BoundSql对象
        BoundSql boundSql = statementHandler.getBoundSql();
        // 原始sql
        String origSql = boundSql.getSql();
        log.info("原始SQL: {}", origSql);
        // 在表名之前添加数据库库前缀 [这里做自己的业务就行]
        String newSql = addDbPrefixBeforeTableName(origSql);
        log.info("修改后SQL: {}", newSql);
        // 使用反射获取属性
        Field field = boundSql.getClass().getDeclaredField("sql");
        field.setAccessible(true);
        // 设置新的属性
        field.set(boundSql, newSql);
        return invocation.proceed();
    }

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

    @Override
    public void setProperties(Properties properties) {
    }

    /**
     * 在表名之前添加数据库库前缀 [处理自己的业务 我这是把sql直接replace]
     *
     * @param sql 原始的sql
     * @return 添加了之后的sql
     */
    private String addDbPrefixBeforeTableName(String sql) {
        try {
           // todo
        } catch (Exception e) {
           // ignore
        }
        return sql;
    }
}
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐