• Mybatis-Plus 使用技巧与隐患


    在这里插入图片描述

    前言

    MP 从出现就一直有争议 感觉一直 都存在两种声音
    转载个人掘金地址

    like:

    很方便啊 通过函数自动拼接Sql 不需要去XML 再去使用标签 之前一分钟写好的Sql 现在一秒钟就能写好 简直不要太方便

    dislike:

    侵入Service层 不好维护 可读性差 代码耦合 效率不行 sql优化比较难

    之前也有前辈说少用MP 理由就是不好维护 但是这个东西真的是方便 只要不是强制不让用 就还是会去使用 存在集合里 最近也确实有一些体会 就从两个角度去看一下MP

    优点

    操作简洁

    就从我们编码中最常用的增删改查去说

    按照我们之前去使用Mybatis的喜欢我们就要去建立一个XML文件 去编写Sql语句 算是半自动 我们可以直接去操控Sql语句 但是会比较麻烦 很多简单的数据查询我们都要去写一个标签 感觉这种没有意义的操作还是比较烦的 那么MP里面怎么实现

    第一种:
    最简单我们就是直接去使用提供的方法 我们非常简单就能做到这些操作 但是这个就有一个问题

    nodeMapper.selectById(1);
    nodeMapper.deleteById(2);
    nodeMapper.updateById(new Node());
    nodeMapper.insert(new Node());
    
    • 1
    • 2
    • 3
    • 4

    维护性差
    以查询为例 这个默认提供的方法都是查询所有字段我们都知道在编写Sql的时候第一条优化准则就是不要使用Select * 因为这种写法是很Low

    这个就是上面selectById执行的结果

     SELECT Id,name,pid FROM node WHERE Id=?
    
    • 1

    这种Sql 肯定是不好的所以我们在使用MP的时候尽量不要去使用自带的快捷查询 我们可以去使用它里面的构造器

    nodeMapper.selectOne(new QueryWrapper<Node>().eq("id",1).select("id"));
    
    • 1

    这汇总写法 我们可以通过后面的select() 去指定我们需要查询的字段 算是解决上面那个问题吗 但是这个就完事了吗? 这还有一个问题

    我们在开发中经常会说一个叫魔法值的东西

    //这个就是魔法值 
    if ("变成派大星".equals(node.getName())){
        System.out.println("魔法值");
    }
    
    • 1
    • 2
    • 3
    • 4

    之所以不要多用魔法值就是为了后期维护 我们建议使用枚举 或者建一个常量类 通过Static final修饰

    上面那段代码是不是也有同样问题 "id"算不算魔法值呢 这种构造器产生的问题就是 不好维护

    假设 我们的这Node类是高度使用的 我们到处都在写

    nodeMapper.selectOne(new QueryWrapper<Node>().eq("id",1).select("id"));
    
    • 1

    刚开始没事 我们乐呵呵的 但是一旦我去修改Id 的字段名怎么办
    在这里插入图片描述

    我修改成test(数据库同步修改) 现在这个实体类中没有这个字段 我们再去看我们的代码

    在这里插入图片描述

    没有什么反应 没有给我提示报错 我这个时候去运行怎么办 我要一个个去找这个错误吗 这明显很费时间

    这个确实是一个问题 但是也是可以解决的

    Node node = nodeMapper.selectOne(new LambdaQueryWrapper<Node>().eq(Node::getId, 1).select(Node::getId));
    
    • 1

    上面这种代码就可以去解决这个问题 我们在使用的时候可以多用这个东西

    在这里插入图片描述

    一旦修改字段就会立马报错

    但是 这就万事大吉了吗 NO No NO 我们要是处理稍微复杂的语句怎么办?
    比如如我们字段求和 这个LambdaQueryWrapper还是存在限制的

    如果我们想实现这种 怎么去做呢

    
    select SUM(price_count) from  bla_order_data LIMIT 100
    
    • 1
    • 2

    首先这种写法肯定是不太行的 编译不通过

    在这里插入图片描述

    除非去使用QueryWrapper

    在这里插入图片描述

    还有就是分页查询

    // 条件查询
    LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(UserInfo::getAge, 20);
    // 分页对象
    Page<UserInfo> queryPage = new Page<>(page, limit);
    // 分页查询
    IPage<UserInfo> iPage = userInfoMapper.selectPage(queryPage , queryWrapper);
    // 数据总数
    Long total = iPage.getTotal();
    // 集合数据
    List<UserInfo> list = iPage.getRecords();
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这个还是非常简单的

    简单总结

    MP 在做一些简单的单表查询可以去使用但是对于一些复杂的SQl操作还是不要用

    1、SQL侵入Service 的问题我们可以仿照 Mybatis 建一个专门存放 MP查询的包

    2、关于维护性 我们可以尽量去使用 LambdaQueryWrapper 去构造

    3、MP是有内置的主键生成策略

    4、内置分页插件:基于 Mybatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通List查询。

    缺点

    我就说一个最大的缺点就是对于复杂Sql 的操作性很不舒服 比如我们去多表查询 你怎么去写呢

    看一个例子

    在这里插入图片描述

    在这里插入图片描述

    就是通过

     @Select 注解
     
     将Mp的查询条件嵌入进去
     ${ew.customSqlSegment}
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    咱就是一整个大问号 联表老老实实去写XML吧 这种真的不要去用 太丑了

    总结

    没有过多的东西 基本都是最近看到的东西

    1、复杂语句不推荐使用MP 能用最好也别用 可读性差 难维护 使用刚开始没感觉 后期业务扩充 真的恶心的

    2、可以使用MP中的分页 比较舒服 逐渐生成策略也舒服

    3、尽量不要去使用MP中自带的selectById 等全表查询的方法

    4、尽量使用LambdaQueryWrapper的书写形式 至少比较好维护

    5、简单重复Sql 可以用MP。复杂SQL不要用

    完结有想到的会补充各位同僚有其他意见可以评论区见 会补充修正

  • 相关阅读:
    Redis和数据库的数据一致性问题
    JS学习之BOM2
    工程伦理--13.3 “邻避效应”中的社会公平问题
    浅说一下 import.meta.glob()
    PAT 甲级常见单词整理
    第五届“强网”拟态防御国际精英挑战赛——预选赛入围战队篇
    TensorFlow入门(七、检查点)
    IELTS-ACADEMIC-15
    如何判断bug是前端bug还是后端bug
    UE5实战篇二(对话系统1):导语
  • 原文地址:https://blog.csdn.net/weixin_44994494/article/details/127694091