如何自定義MyBatis攔截器更改表名
自定義MyBatis攔截器可以在方法執(zhí)行前后插入自己的邏輯,這非常有利于擴(kuò)展和定制 MyBatis 的功能。本篇文章實(shí)現(xiàn)自定義一個攔截器去改變要插入或者查詢的數(shù)據(jù)源。
@Intercepts
@Intercepts是Mybatis的一個注解,它的主要作用是標(biāo)識一個類為攔截器。該注解通過一個@Signature注解(即攔截點(diǎn)),來指定攔截那個對象里面的某個方法。
具體來說,@Signature注解的屬性type用于指定攔截器類型,可能的值包括:
- Executor(sql的內(nèi)部執(zhí)行器)
- ParameterHandler(攔截參數(shù)的處理)
- StatementHandler(攔截sql的構(gòu)建)
- ResultSetHandler(攔截結(jié)果的處理)。
method屬性表示在指定的攔截器類型中要攔截的方法
args屬性表示攔截的方法對應(yīng)的參數(shù)
實(shí)現(xiàn)步驟
實(shí)現(xiàn)org.apache.ibatis.plugin.Interceptor
接口,重寫一下的方法:
添加攔截器注解,@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
配置文件中添加攔截器
注意需要在 Spring Boot 的 application.yml 文件中配置 mybatis 配置文件的路徑。
mybatis攔截器目前不支持在application.yml配置文件中通過屬性配置,目前只支持通過xml配置或者代碼配置。
代碼實(shí)現(xiàn)
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"); // 獲取自定義注解判斷是否進(jìn)行分表操作 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); } }
運(yùn)行結(jié)果
通過上圖可以看出,現(xiàn)在表名已經(jīng)修改成了score_2
了。通過這種機(jī)制,我們可以應(yīng)用到自動分表中。本文的表名的索引是通過注解參數(shù)傳遞的,實(shí)際應(yīng)用中需要通過哈希散列計(jì)算。
到此這篇關(guān)于自定義MyBatis攔截器更改表名的文章就介紹到這了,更多相關(guān)MyBatis攔截器更改表名內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于jenkins構(gòu)建結(jié)果企業(yè)微信提醒
這篇文章主要介紹了基于jenkins構(gòu)建結(jié)果企業(yè)微信提醒,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08Spring中的FactoryBean實(shí)現(xiàn)原理詳解
這篇文章主要介紹了Spring中的FactoryBean實(shí)現(xiàn)原理詳解,spring中有兩種類型的Bean,一種是普通的JavaBean,另一種就是工廠Bean(FactoryBean),這兩種Bean都受Spring的IoC容器管理,但它們之間卻有一些區(qū)別,需要的朋友可以參考下2024-02-02vue+springboot讀取git的markdown文件并展示功能
Markdown-it 是一個用于解析和渲染 Markdown 標(biāo)記語言的 JavaScript 庫,使用 Markdown-it,你可以將 Markdown 文本解析為 HTML 輸出,并且可以根據(jù)需要添加功能、擴(kuò)展語法或修改解析行為,本文介紹vue+springboot讀取git的markdown文件并展示,感興趣的朋友一起看看吧2024-01-01Java替換int數(shù)組中重復(fù)數(shù)據(jù)的方法示例
這篇文章主要介紹了Java替換int數(shù)組中重復(fù)數(shù)據(jù)的方法,涉及java針對數(shù)組的遍歷、轉(zhuǎn)換、判斷等相關(guān)操作技巧,需要的朋友可以參考下2017-06-06基于EasyExcel實(shí)現(xiàn)百萬級數(shù)據(jù)導(dǎo)入導(dǎo)出詳解
大數(shù)據(jù)的導(dǎo)入和導(dǎo)出,相信大家在日常的開發(fā)、面試中都會遇到。本文將為大家詳細(xì)介紹一下如何利用EasyExcel實(shí)現(xiàn)百萬級數(shù)據(jù)導(dǎo)入導(dǎo)出,需要的可以參考一下2023-01-01JAVA使用hutool工具實(shí)現(xiàn)查詢樹結(jié)構(gòu)數(shù)據(jù)(省市區(qū))
今天通過本文給大家分享JAVA使用hutool工具實(shí)現(xiàn)查詢樹結(jié)構(gòu)數(shù)據(jù)(省市區(qū)),代碼分為表結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu),代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2021-08-08Java利用SpEL表達(dá)式實(shí)現(xiàn)權(quán)限校驗(yàn)
這篇文章主要為大家詳細(xì)介紹了Java如何利用SpEL表達(dá)式實(shí)現(xiàn)權(quán)限校驗(yàn)功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01