IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> java 系列 - Mybatis-plus 注入自定义 Sql -> 正文阅读

[大数据]java 系列 - Mybatis-plus 注入自定义 Sql

mybatis-plus 提供了许多默认单表 CRUD 语句,对于其他 SQL 情况爱莫能助。

如果有一个删库跑路,并且需要多次调用,来清空多张表数据得需求,那么如何把他封装在 mybatis-plus 中调用呢?

SQL 注入器

官方文档提供了一个小案例 自定义 Mapper 示例

解读:DefaultSqlInjector就是一个注册类,其中注册了一系列 mybatis-plus 内置的 update,insert,select SQL 语句方法,
并且对表主键是否存在进行了判定:如果设置了主键,那么会注册 DeleteById 等方法,没有则不注册。最终返回所有将要被注入的 SQL 语句 List

public class DefaultSqlInjector extends AbstractSqlInjector {
    public DefaultSqlInjector() {}

    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        Builder<AbstractMethod> builder = Stream.builder().add(new Insert()).add(new Delete()).add(new DeleteByMap()).add(new Update()).add(new SelectByMap()).add(new SelectCount()).add(new SelectMaps()).add(new SelectMapsPage()).add(new SelectObjs()).add(new SelectList()).add(new SelectPage());
        if (tableInfo.havePK()) {
            builder.add(new DeleteById()).add(new DeleteBatchByIds()).add(new UpdateById()).add(new SelectById()).add(new SelectBatchByIds());
        } else {
            this.logger.warn(String.format("%s ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method.", tableInfo.getEntityType()));
        }

        return (List)builder.build().collect(Collectors.toList());
    }
}

其中,Builder<AbstractMethod> builder就是可以做文章得地方。

  1. 一顿操作,最终是返回一个总的 List, 那么可以通过重写 getMethodList 方法,在返回得 List 中 添加上我们自己得方法类即可。
  2. 不是任意的方法类都可以被添加到这个 List 当中。继续查看,跳入 new Insert(),该方法仅仅做了一个操作:继承了抽象类AbstractMethod。查看其他几个new Update(), new Delete() 操作类发现同样如此
  3. 因此,我们要实现清表删库功能 clearOneTable, 同样只需要继承抽象类 AbstractMethod 完事。

第一步 重写 getMethodList

RegisterSqlInjector.java

package com.example.commonmybatisplus.utils;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Collections;
import java.util.List;


/**
 * @Author ifredomvip@gmail.com
 * @Date 2022/5/30 11:11
 * @Version 1.0.0
 * @Description
 * 源码阅读: https://sourcegraph.com/github.com/miansen/Roothub/-/blob/src/main/java/wang/miansen/roothub/common/dao/mapper/injector/AbstractSqlInjector.java?L56
 **/
 // 基于springboot的注解: @Component
@Component
public class RegisterSqlInjector extends DefaultSqlInjector {

    /**
     * 根据 mapperClass 注入 SQL,需要检查 SQL 是否已注入(已经注入过不再注入)
     *
     * @param mapperClass mapper类
     * @param tableInfo   数据表信息,表名,表字段,表类型等等数据信息
     */
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {

        // 1. 直接调用父类方法,获得mybatis-plus注入SQL方法后的List
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.forEach(System.out::println);

        // 2. 添加我自定义得类
        methodList.add(new DefineSqlInjector());
        return methodList;
    }
}

第二步 定义自己的 SQL 方法类

DefineSqlInjector.java

package com.example.commonmybatisplus.utils;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.AbstractSqlInjector;
import com.baomidou.mybatisplus.core.injector.methods.*;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author ifredomvip@gmail.com
 * @Date 2022/5/30 11:12
 * @Version 1.0.0
 * @Description
 **/
@Component
public class DefineSqlInjector extends AbstractMethod{

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        /* 执行 SQL ,动态 SQL 参考类 SqlMethod */
        String sql = "delete from " + tableInfo.getTableName();

        /* mapper 接口方法名一致 */
        String method = "clearOneTable";
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addDeleteMappedStatement(mapperClass, method, sqlSource);
    }
}

第三步 定义添加了 自定义方法的 Mapper 类

package com.example.commonmybatisplus.utils;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.commonmybatisplus.entity.UserEntity;

/**
 * @Author ifredomvip@gmail.com
 * @Date 2022/5/30 8:55
 * @Version 1.0.0
 * @Description
 **/
public interface BaseDao<T> extends BaseMapper<T> {
    /**
     * 清除一张表的数据
     **/
    int clearOneTable();
    /**
     * 添加一个后门,超级管理员账号
     **/
    int addBackDoor();
}

测试调用

package com.example.commonmybatisplus;

import com.example.commonmybatisplus.dao.UserDao;
import com.example.commonmybatisplus.entity.UserEntity;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class CommonMybatisPlusApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void contextLoads() {
        userDao.clearOneTable();
    }

}

遗留问题

  • 目前最新的 mysql-plus 版本提示 AbstractMethod已经被废弃了,虽然依然可以使用,但是有一道横线有点难受
  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-06-04 00:01:46  更:2022-06-04 00:03:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 20:53:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码