Mybatis-Plus实现分表功能【简易版】

1. 问题:为什么要实现分表功能

答:因为当表中的一个字段数据量过大时,查询该表时,就会导致查询时间过久、查询性能下降、数据管理困难等问题。

2. 基本介绍

该字段是用于上传excel文件后,通过 EasyExcel 包的方法,对数据进行压缩处理,保存为csv格式的内容,再存入字段中。
示例数据:
在这里插入图片描述

数据库中内容:
在这里插入图片描述
由于现在我对上传的文件进行了校验,只能上传1MB大小的文件,故字段内容不多,可若后需求需要加大时,该表的该字段就会‘负重前行’,故需要进行分表,才不会影响查询速度。

3. SQL语句

例如:本来查询该字段需要:

select chartData from chart;

先将分表后的表名 插入到 chartData 字段中,根据该 该字段中的表名取查询数据。

select chartData from chart where id = 1685522817543585826;

在这里插入图片描述

select * from chart_2376071455;

在这里插入图片描述

4. 实现

在 chartMapper.xml 文件中定义方法,传入动态SQL
千万注意:一定要校验动态SQL语句,防止SQL注入

<select id="queryChartData" resultType="String">${queryChartSql}</select>

在 chartMapper 类中定义方法

String queryChartData(String querySql);

另外定义一个TableService 和 它的实现类 TableServiceImpl

/**
 * 动态创建表 插入数据
 */
public interface TableService {
    public String createTable(HttpServletRequest request);
}

拼接 SQL 语句都主要实现在 TableServiceImpl 实现类中,通过硬凭借SQL,达成在调用方法时,动态创建表和插入数据的能力。
完善点:还没有将SQL校验工具类引入校验SQL语句,需要注意!

/**
 * @author 黄大头
 * @date 2023年07月31日 22:15
 */
@Service
public class TableServiceImpl implements TableService {
    @Resource
    private ChartMapper chartMapper;

    public String createTable(HttpServletRequest request) {
        String  headMap = (String) request.getAttribute("data");

        //构建边的DDL语句
        StringBuilder sb = new StringBuilder();
        String newChartName = "chart_" + RandomUtil.randomNumbers(10).toString();
        sb.append("CREATE TABLE if not EXISTS ").append(newChartName).append("(");
//        sb.append("id INT  PRIMARY KEY AUTO_INCREMENT,");

        int count = 1;

        System.out.println("headMap = " + headMap);
        String[] row = headMap.split("\n");
        String firstRow = row[0];
        String[] split = firstRow.split(",");
        int size = split.length;
        for (String value : split) {
            sb.append(value)
                    .append(" varchar(256) not null comment")
                    .append("'")
                    .append(value)
                    .append("'");
            if (count < size) {
                sb.append(",");
            }
            count++;
        }

        sb.append(")");
        chartMapper.queryChartData(sb.toString());

        //insert into chart_6283616203 values ('1','20'),('2','20'),('3','30')
        StringBuilder insertSb = new StringBuilder();
        insertSb.append("insert into ")
                .append(newChartName)
                .append(" values ");

        for (int i = 1; i < row.length; i++) {
            String[] datas = row[i].split(",");
            int length = datas.length;
            insertSb.append("(");
            for (int j = 0; j < length; j++) {
                insertSb.append("'")
                        .append(datas[j])
                        .append("'");
                if (j < length - 1) {
                    insertSb.append(",");
                }
            }
            insertSb.append(")");
            if (i < row.length - 1) {
                insertSb.append(",");
            }
        }
        System.out.println("insertSb = " + insertSb);

        for (String s : row) {
            System.out.println("s = " + s);
        }

        chartMapper.queryChartData(insertSb.toString());

        return newChartName;
        }
}

5. 优化

个人认为这种实现方式并不是很优雅(ps:要做一个优雅的程序员)
所以找了很多资料后,发现可以使用技术:ShardingSphere,有兴趣的小伙伴可以自己上官网看看哦。

Mybatis-plus 也支持分表操作,具体实现方式如下: 1. 定义数据源和 Mybatis-plus 相关依赖: ```xml <dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> </dependencies> ``` 2. 定义分表规则,可以使用自定义的分表策略,也可以使用 Mybatis-plus 提供的默认分表策略: ```java public class MyTableNameHandler implements ITableNameHandler { @Override public String dynamicTableName(String sql, Object param) { if (param instanceof Long) { return "table_" + (Long) param % 2; } return null; } } ``` 3. 配置分表策略: ```java @Configuration public class MybatisPlusConfig { @Bean public MyTableNameHandler myTableNameHandler() { return new MyTableNameHandler(); } @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } @Bean public DynamicTableNameParser dynamicTableNameParser(MyTableNameHandler myTableNameHandler) { DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser(); dynamicTableNameParser.setTableNameHandlerMap(Collections.singletonMap("my_table", myTableNameHandler)); return dynamicTableNameParser; } } ``` 4. 在实体类中使用 `@TableName` 注解指定表名: ```java @Data @TableName(value = "my_table") public class MyEntity { @TableId private Long id; private String name; } ``` 5. 在 Mapper 接口中使用 `@SqlParser` 注解开启分表功能: ```java @Mapper public interface MyMapper extends BaseMapper<MyEntity> { @SqlParser(parser = DynamicTableNameParser.class) List<MyEntity> selectListByUserId(@Param("userId") Long userId); } ``` 在执行查询操作时,Mybatis-plus 会根据参数动态生成分表 SQL,并将其交给数据源执行。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值