侧边栏壁纸
  • 累计撰写 15 篇文章
  • 累计创建 8 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

sql代码批量生成工具(使用mybatis-plus的API)

王富贵
2024-05-19 / 0 评论 / 7 点赞 / 122 阅读 / 0 字

sql代码批量生成工具

1、思路原理

开源地址:sql-gen-tools: 批量生成sql脚本

背景:即兴想借用mybatis-plus的api生成sql。调用mybatis-plus的sql执行接口,即可批量生成sql执行脚本。

原理:执行sql语法的时候使用拦截器拦截sql session执行,获取到最终sql并使用io流输出到本地文件中。

核心代码:com.fg.core.ReplacePlaceholderInnerInterceptor

核心执行逻辑:

  1. com.fg.core.ReplacePlaceholderInnerInterceptor
    1. 动态表名插件
    2. 获取boundSql进行占位符替换
    3. 抛出NormalTerminationException正常退出的异常,保证sql不会最终的执行
  2. com.fg.core.MapperExceptionAspect
    1. 环绕api的执行方法,捕获正常退出的方法,并返回对应类型的空返回

2、业务背景

痛点1

业务甩几万甚至几十万数据,要我们确定库内是否有该数据。在没有数仓场景下我们只能使用sql去线上库查,但需要避免大批量查询打爆线上库或者库工具只支持有限的查询。因此该工具支持使用mybatis-plus的api批量生成sql。

痛点2

业务说这几十万数据,库内有的需要订正成逻辑删除状态,且每次只有删除60条才能避免对数据库照成影响,且该数量庞大,就需要工具生成。

例如我们需要生成以下格式sql

update test_table 
set is_delete=1 
where (
    (姓名 = '张三' and gender = '男' and focus = '无' and age = '33') 
    or (姓名 = '李四' and gender = '男' and focus = '好对象' and age = '23') 
    or (姓名 = '王妹妹' and gender = '女' and focus = '特别关注' and age = '22')
    。。。
    以下省略60or
    。。。
)

3、使用方法

继承com.fg.generaltor.BaseGeneralGenerator,核心方法均在该类里面。将实现类注入spring容器,重写process方法,内部可以使用generalTableMapper调用mybatis-plus的api,即可生成sql脚本,你也可以封装成web接口。

样例类:

  • com.fg.generaltor.SimpleTestGenerator
  • com.fg.generaltor.TestGenerator

你可以自己运行一次,即可通过样例类生成其对应的sql脚本尝鲜。

默认输出sql文件位置

默认输出文件位置在当前jar包目录下,如果你是idea运行的,路径如下:target/classes/fileName.sql

输入图片说明

例:com.fg.generaltor.TestGenerator。

import cn.hutool.core.text.csv.CsvUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fg.entity.GeneralTable;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;

/**
 * @author: 王富贵
 * @description: 测试sql生成器
 * @createTime: 2024年04月20日 23:31:41
 */
@Component
public class TestGenerator extends BaseGenerator {
    @Override
    protected void setTableName() {
        super.setTableName("我是动态表哦");
    }

    @Override
    public void process() {
        // 测试1

        // 设置每批数量
        setBatchCount(3);
        setOutPutFileName("TestGenerator");
        setTableName("test_generator_table_name");

        List<Map<String, String>> userMapsList;
        try {
            userMapsList = CsvUtil.getReader().readMapList(new FileReader(ResourceUtils.getFile("classpath:test.csv")));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        /*  目标格式
            update test_table set is_delete = 1
            where (
            (id = '1003' and 姓名 = '张三' and gender = '男' and focus = '无' and age = '33')
            or (id = '2006' and 姓名 = '李四' and gender = '男' and focus = '好对象' and age = '23')
            or (id = '3009' and 姓名 = '王妹妹' and gender = '女' and focus = '特别关注' and age = '22')
            )
         */
        batchUpdate(userMapsList,
                new BiConsumer<UpdateWrapper<GeneralTable>, List<Map<String, String>>>() {
                    @Override
                    public void accept(UpdateWrapper<GeneralTable> updateWrapper, List<Map<String, String>> maps) {
                        updateWrapper.set("is_delete", 1);
                    }
                },
                new BiConsumer<UpdateWrapper<GeneralTable>, Map<String, String>>() {
                    @Override
                    public void accept(UpdateWrapper<GeneralTable> updateWrapper, Map<String, String> stringStringMap) {
                        updateWrapper.or(updateWrapperTmp -> updateWrapperTmp.allEq(stringStringMap));
                    }
                });
        /*  目标格式
            select id,name,age,email from test_table where (id in (1003,2006,3009))
         */
        batchSelect(userMapsList,
                new BiConsumer<QueryWrapper<GeneralTable>, List<Map<String, String>>>() {
                    @Override
                    public void accept(QueryWrapper<GeneralTable> queryWrapper, List<Map<String, String>> maps) {
                        List<Long> ids = maps.stream()
                                .map(map -> map.get("id")) // 提取每个 Map 对象的 id 值
                                .filter(id -> id != null && id.matches("\\d+")) // 过滤非空且符合数字格式的 id
                                .map(Long::parseLong) // 将字符串 id 转换为 Long 类型
                                .collect(Collectors.toList()); // 收集成一个 List<Long>
                        queryWrapper.in("id", ids);
                    }
                },
                (BiConsumer<QueryWrapper<GeneralTable>, Map<String, String>>) (queryWrapper, userMaps) -> {
                }
        );


        /**
         * 测试2
         */
        // 设置每批数量
        setBatchCount(60);
        try {
            userMapsList = CsvUtil.getReader().readMapList(new FileReader(ResourceUtils.getFile("classpath:test.csv")));
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }
        batchUpdate(userMapsList,
                new BiConsumer<UpdateWrapper<GeneralTable>, List<Map<String, String>>>() {
                    @Override
                    public void accept(UpdateWrapper<GeneralTable> updateWrapper, List<Map<String, String>> maps) {
                        updateWrapper.set("is_delete", 1);
                    }
                },
                new BiConsumer<UpdateWrapper<GeneralTable>, Map<String, String>>() {
                    @Override
                    public void accept(UpdateWrapper<GeneralTable> updateWrapper, Map<String, String> stringStringMap) {
                        updateWrapper.or(updateWrapperTmp -> updateWrapperTmp.allEq(stringStringMap));
                    }
                });

        /**
         * 测试3
         */
        // 动态表名实现表名变更
        setTableName("tools");
        QueryWrapper<GeneralTable> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", 1).eq("email_name", "li");
        generalTableMapper.delete(queryWrapper);

        /**
         * 测试4
         */
        UpdateWrapper<GeneralTable> updateWrapper = new UpdateWrapper<>();
        ArrayList<Integer> ids = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            ids.add(i);
        }
        updateWrapper.in("id", ids);
        updateWrapper.set("name", "富??贵");
        generalTableMapper.update(updateWrapper);
    }
}
7

评论区