自定义MyBatis拦截器更改表名

这篇具有很好参考价值的文章主要介绍了自定义MyBatis拦截器更改表名。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

by emanjusaka from ​ https://www.emanjusaka.top/2023/10/mybatis-interceptor-update-tableName 彼岸花开可奈何
本文欢迎分享与聚合,全文转载请留下原文地址。

自定义MyBatis拦截器可以在方法执行前后插入自己的逻辑,这非常有利于扩展和定制 MyBatis 的功能。本篇文章实现自定义一个拦截器去改变要插入或者查询的数据源。

@Intercepts

@Intercepts是Mybatis的一个注解,它的主要作用是标识一个类为拦截器。该注解通过一个@Signature注解(即拦截点),来指定拦截那个对象里面的某个方法。

具体来说,@Signature注解的属性type用于指定拦截器类型,可能的值包括:

  • Executor(sql的内部执行器)
  • ParameterHandler(拦截参数的处理)
  • StatementHandler(拦截sql的构建)
  • ResultSetHandler(拦截结果的处理)。

method属性表示在指定的拦截器类型中要拦截的方法

args属性表示拦截的方法对应的参数

实现步骤

  1. 实现org.apache.ibatis.plugin.Interceptor接口,重写一下的方法:

  2. 添加拦截器注解,@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})

  3. 配置文件中添加拦截器

    注意需要在 Spring Boot 的 application.yml 文件中配置 mybatis 配置文件的路径。

    mybatis拦截器目前不支持在application.yml配置文件中通过属性配置,目前只支持通过xml配置或者代码配置。

代码实现

Mybatis拦截器:

package top.emanjusaka.springboottest.mybatis.plugin;

import org.apache.ibatis.executor.statement.StatementHandler;
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.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import top.emanjusaka.springboottest.mybatis.annotation.DBTableStrategy;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Author emanjusaka
 * @Date 2023/10/18 17:25
 * @Version 1.0
 */
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DynamicMybatisPlugin implements Interceptor {
    private Pattern pattern = Pattern.compile("(from|into|update)[\\s]{1,}(\\w{1,})", Pattern.CASE_INSENSITIVE);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        // 获取自定义注解判断是否进行分表操作
        String id = mappedStatement.getId();
        String className = id.substring(0, id.lastIndexOf("."));
        Class<?> clazz = Class.forName(className);
        DBTableStrategy dbTableStrategy = clazz.getAnnotation(DBTableStrategy.class);
        if (null == dbTableStrategy || !dbTableStrategy.changeTable() || null == dbTableStrategy.tbIdx()) {
            return invocation.proceed();
        }
        // 获取SQL
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        // 替换SQL表名
        Matcher matcher = pattern.matcher(sql);
        String tableName = null;
        if (matcher.find()) {
            tableName = matcher.group().trim();
        }
        assert null != tableName;
        String replaceSql = matcher.replaceAll(tableName + "_" + dbTableStrategy.tbIdx());
        // 通过反射修改SQL语句
        Field field = boundSql.getClass().getDeclaredField("sql");
        field.setAccessible(true);
        field.set(boundSql, replaceSql);
        field.setAccessible(false);
        return invocation.proceed();
    }
}

mapper的xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.emanjusaka.springboottest.score.repository.IScoreRepository">
    <select id="selectAll" resultType="top.emanjusaka.springboottest.score.model.vo.ScoreVO">
        select * from score
    </select>
</mapper>

切换表名的注解:

package top.emanjusaka.springboottest.score.repository;

import org.apache.ibatis.annotations.Mapper;
import top.emanjusaka.springboottest.mybatis.annotation.DBTableStrategy;
import top.emanjusaka.springboottest.score.model.vo.ScoreVO;

import java.util.List;

/**
 * @Author emanjusaka
 * @Date 2023/10/18 17:45
 * @Version 1.0
 */
@Mapper
@DBTableStrategy(changeTable = true,tbIdx = "2")
public interface IScoreRepository {
    List<ScoreVO> selectAll();
}

测试代码:

package top.emanjusaka.springboottest;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import top.emanjusaka.springboottest.score.model.vo.ScoreVO;
import top.emanjusaka.springboottest.score.service.IScore;

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

@SpringBootTest
class SpringBootTestApplicationTests {
    @Resource
    private IScore score;
    @Test
    void contextLoads() {
        List<ScoreVO> list = score.selectAll();
        list.forEach(System.out::println);
    }

}

运行结果

通过上图可以看出,现在表名已经修改成了score_2了。通过这种机制,我们可以应用到自动分表中。本文的表名的索引是通过注解参数传递的,实际应用中需要通过哈希散列计算。

本文原创,才疏学浅,如有纰漏,欢迎指正。如果本文对您有所帮助,欢迎点赞,并期待您的反馈交流,共同成长。
原文地址: https://www.emanjusaka.top/2023/10/mybatis-interceptor-update-tableName
微信公众号:emanjusaka的编程栈文章来源地址https://www.toymoban.com/news/detail-711460.html

到了这里,关于自定义MyBatis拦截器更改表名的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MyBatis拦截器优雅实现数据脱敏

    现代网络环境中,敏感数据的处理是至关重要的。敏感数据包括个人身份信息、银行账号、手机号码等,泄露这些数据可能导致用户隐私泄露、财产损失等严重后果。因此,对敏感数据进行脱敏处理是一种必要的安全措施。 比如页面上常见的敏感数据都是加*遮挡处理过的,

    2024年02月06日
    浏览(33)
  • 自定义注解与拦截器实现不规范sql拦截(拦截器实现篇)

    最近考虑myBatis中sql语句使用规范的问题,如果漏下条件或者写一些不规范语句会对程序性能造成很大影响。最好的方法就是利用代码进行限制,通过拦截器进行sql格式的判断在自测环节就能找到问题。写了个简单情景下的demo,并通过idea插件来将myBatis的mapper方法都打上拦截器

    2024年01月22日
    浏览(36)
  • MyBatis Plus 拦截器实现数据权限控制

    上篇文章介绍的MyBatis Plus 插件实际上就是用拦截器实现的,MyBatis Plus拦截器对MyBatis的拦截器进行了包装处理,操作起来更加方便 2.1、InnerInterceptor MyBatis Plus提供的InnerInterceptor接口提供了如下方法,主要包括:在查询之前执行,在更新之前执行,在SQL准备之前执行 2.2、编写简

    2024年01月17日
    浏览(33)
  • 自定义拦截器实现

    在 Spring MVC 框架中, 拦截器作为一种机制, 用于对请求进行拦截. 拦截器可以在请求进入处理器之前、处理器返回处理之后、视图渲染之前等各个环节进行拦截. 拦截器通常用于实现一下功能 : 鉴权和身份认证 日志记录和统计 请求参数和校验和过滤 缓存和性能优化 路径重定向

    2024年02月09日
    浏览(40)
  • flume自定义拦截器

    要自定义 Flume 拦截器,你需要编写一个实现 org.apache.flume.interceptor.Interceptor 接口的自定义拦截器类。以下是一个简单的示例: 在上面的示例中,我们实现了 initialize() 、 intercept() 、 intercept(ListEvent events) 、 close() 方法来定义自定义拦截器的行为。你可以根据需要在这些方法中

    2024年01月23日
    浏览(32)
  • 自定义拦截器(OpenFeign)

    全量的调用日志中可以查看到自定义拦截器增加的 custom_header_info 字段

    2024年01月19日
    浏览(27)
  • Mybatis拦截器注解@Intercepts与@Signature注解属性说明

    可能有些新手使用mybatis拦截器的时候可能没太懂@Signature注解中type,method,args的用法 首先mybatis拦截器可以拦截如下4中类型 Executor sql的内部执行器 ParameterHandler 拦截参数的处理 StatementHandler 拦截sql的构建 ResultSetHandler 拦截结果的处理 type:就是指定拦截器类型(ParameterHandl

    2024年02月05日
    浏览(35)
  • WebService 客户端增加Header头、并且指定命名空间、添加拦截器(日志拦截器,自定义拦截器)、soap:Envelope 添加命名空间

    1.增加Header头 生成XML结果如下 2.添加拦截器 3.soap:Envelope 添加命名空间 生成XML结果如下

    2024年02月10日
    浏览(37)
  • Springboot中自定义拦截器

    Spring Boot 中使用拦截器 参考:https://blog.csdn.net/taojin12/article/details/88342576?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170823498416800197050192%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257Drequest_id=170823498416800197050192biz_id=0utm_medium=distribute.pc_search_result.none-task-blog-2 all top_positive~defa

    2024年02月19日
    浏览(40)
  • 自定义注解与拦截器实现不规范sql拦截(自定义注解填充插件篇)

    在自定义注解与拦截器实现不规范sql拦截(拦截器实现篇)中提到过,写了一个idea插件来辅助对Mapper接口中的方法添加自定义注解,这边记录一下插件的实现。 在上一篇中,定义了一个自定义注解对需要经过where判断的Mapper sql方法进行修饰。那么,现在想使用一个idea插件来

    2024年01月23日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包