注意:本教程使用的数据库脚本、数据模型和环境信息请参考 “MyBatis Plus环境准备” 章节,点击下载示例源码。
本文将介绍 MyBatis Plus 的 DynamicTableNameInnerInterceptor 插件,使用该插件实现表名动态替换。
当数据量比较大的时候,为了提高数据库操作的效率,尤其是查询的效率,其中一种解决方案就是将数据表拆分。 拆分的数据表,结构完全一致,只不过是表的名字,按照某种规律,而成为一组。
例如:日志表(log),我们可以根据年份选择表格,如:log_2018、log_2019、log_2020 等。其中,log_2018 表格只存放 2018 年的日志信息,其他年份类推。
MyBatis Plus 提供的 DynamicTableNameInnerInterceptor 插件就是用来解决动态表名。同时,还提供了 TableNameHandler 接口,该接口有一个 dynamicTableName() 方法,该方法返回新的表名称。接口代码定义如下:
package com.baomidou.mybatisplus.extension.plugins.handler; /** * @author miemie * @since 3.4.0 */ public interface TableNameHandler { /** * 生成动态表名 * @param sql 当前执行 SQL * @param tableName 表名 * @return String */ String dynamicTableName(String sql, String tableName); }
可以通过 DynamicTableNameInnerInterceptor 插件的 setTableNameHandlerMap(Map<String, TableNameHandler > map) 方法设置每个表对应的 TableNameHandler。在进行 SQL 操作时,sql 对应的表存在 TableNameHandler,则调用 dynamicTableName() 方法获得新的表名称,用新的表名称替换旧的表名称。例如:
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 动态表名插件 DynamicTableNameInnerInterceptor dynamicTabNameInterceptor = new DynamicTableNameInnerInterceptor(); Map<String, TableNameHandler> tableNameHandlerMap = new HashMap<>(); tableNameHandlerMap.put("log", new TableNameHandler() { @Override public String dynamicTableName(String sql, String tableName) { // 将随机的从 log_2018、log_2019 和 log_2020 表中获取数据 // 在实际业务中,这种实现没有什么实际意义 String[] tableSuffix = {"2018", "2019", "2020"}; return tableName + "_" + tableSuffix[(int)(Math.random() * tableSuffix.length)]; } }); dynamicTabNameInterceptor.setTableNameHandlerMap(tableNameHandlerMap); interceptor.addInnerInterceptor(dynamicTabNameInterceptor);
(1)配置 DynamicTableNameInnerInterceptor 插件,如下:
package com.hxstrive.mybatis_plus; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler; import com.baomidou.mybatisplus.extension.plugins.inner.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor paginationInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 动态表名插件 DynamicTableNameInnerInterceptor dynamicTabNameInterceptor = new DynamicTableNameInnerInterceptor(); Map<String, TableNameHandler> tableNameHandlerMap = new HashMap<>(); tableNameHandlerMap.put("log", new TableNameHandler() { @Override public String dynamicTableName(String sql, String tableName) { String[] tableSuffix = {"2018", "2019", "2020"}; return tableName + "_" + tableSuffix[(int)(Math.random() * tableSuffix.length)]; } }); dynamicTabNameInterceptor.setTableNameHandlerMap(tableNameHandlerMap); interceptor.addInnerInterceptor(dynamicTabNameInterceptor); return interceptor; } }
(2)客户端代码,如下:
package com.hxstrive.mybatis_plus.plugins; import com.hxstrive.mybatis_plus.mapper.LogMapper; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest class PluginDemo5 { @Autowired private LogMapper mapper; @Test void contextLoads() { mapper.selectById(1); } }
运行上面代码,将运行下面 sql 语句:
Preparing: SELECT log_id,summary,create_date FROM log_2019 WHERE log_id=? Parameters: 1(Integer)
注意:上面代码中 LogMapper 和前面章节定义的 SimpleMapper一样,均继承自 BaseMapper。