热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Mybatisplus详解如何注入自定义的SQL【mysql优化】

mybatis-plus 提供了许多默认单表 CRUD 语句,对于其他 SQL 情况爱莫能助。如果有一个删库跑路,并且需要多次调用

Mybatisplus详解如何注入自定义的SQL

SQL 注入器

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

解读:DefaultSqlInjector就是一个注册类,其中注册了一系列 mybatis-plus 内置的 update,insert,select SQL 语句方法,

并且对表主键是否存在进行了判定:如果设置了主键,那么会注册 DeleteById 等方法,没有则不注册。最终返回所有将要被注入的 SQL 语句 List

public class DefaultSqlInjector extends AbstractSqlInjector {
    public DefaultSqlInjector() {}
    public List getMethodList(Class mapperClass, TableInfo tableInfo) {
        Builder 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 builder就是可以做文章得地方。

  • 一顿操作,最终是返回一个总的 List, 那么可以通过重写 getMethodList 方法,在返回得 List 中 添加上我们自己得方法类即可。
  • 不是任意的方法类都可以被添加到这个 List 当中。继续查看,跳入 new Insert(),该方法仅仅做了一个操作:继承了抽象类AbstractMethod。查看其他几个new Update(), new Delete() 操作类发现同样如此
  • 因此,我们要实现清表删库功能 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 getMethodList(Class mapperClass, TableInfo tableInfo) {
        // 1. 直接调用父类方法,获得mybatis-plus注入SQL方法后的List
        List 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 extends BaseMapper {
    /**
     * 清除一张表的数据
     **/
    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已经被废弃了,虽然依然可以使用,但是有一道横线有点难受

到此这篇关于Mybatisplus详解如何注入自定义的SQL的文章就介绍到这了,更多相关Mybatisplus注入SQL内容请搜索编程笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程笔记!


推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文介绍了如何在MySQL中将零值替换为先前的非零值的方法,包括使用内联查询和更新查询。同时还提供了选择正确值的方法。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • ubuntu用sqoop将数据从hive导入mysql时,命令: ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • Java学习笔记之使用反射+泛型构建通用DAO
    本文介绍了使用反射和泛型构建通用DAO的方法,通过减少代码冗余度来提高开发效率。通过示例说明了如何使用反射和泛型来实现对不同表的相同操作,从而避免重复编写相似的代码。该方法可以在Java学习中起到较大的帮助作用。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • MySQL中的MVVC多版本并发控制机制的应用及实现
    本文介绍了MySQL中MVCC的应用及实现机制。MVCC是一种提高并发性能的技术,通过对事务内读取的内存进行处理,避免写操作堵塞读操作的并发问题。与其他数据库系统的MVCC实现机制不尽相同,MySQL的MVCC是在undolog中实现的。通过undolog可以找回数据的历史版本,提供给用户读取或在回滚时覆盖数据页上的数据。MySQL的大多数事务型存储引擎都实现了MVCC,但各自的实现机制有所不同。 ... [详细]
author-avatar
星宿1970_219
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有