注意:本教程使用的数据库脚本、数据模型和环境信息请参考 “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。