加班被丈夫赶出家门,HR 辞退我,只因分不清 LambdaQueryWrapper 和 BaseMapper
MyBatis-Plus 核心组件关系BaseMapper、IService、QueryWrapper、LambdaQueryWrapper 大白话讲解一、先看一张关系图心中有数┌──────────────────────────────────────────────────────┐ │ IServiceT │ │ Service层接口继承自...谁往下看 │ │ │ │ 内部持有一个 BaseMapperT给它加了很多便捷方法 │ │ 比如 saveBatch()、saveOrUpdate() 等批量/链式操作 │ └──────────────┬───────────────────────────────────────┘ │ 包装 / 增强 ▼ ┌──────────────────────────────────────────────────────┐ │ BaseMapperT │ │ Mapper层接口最底层的数据库操作 │ │ │ │ 方法签名长这样 │ │ selectList(QueryWrapperT wrapper) │ │ selectOne(QueryWrapperT wrapper) │ │ update(T entity, QueryWrapperT wrapper) │ │ delete(QueryWrapperT wrapper) │ └──────────────┬───────────────────────────────────────┘ │ 方法参数用的是 ▼ ┌──────────────────────────────────────────────────────┐ │ AbstractWrapperT, R, Children │ │ 抽象父类 │ │ / \ │ │ QueryWrapperT LambdaQueryWrapperT │ │ 字符串写列名 Lambda写列名 │ │ │ │ eq(name, 张三) eq(User::getName, 张三) │ │ 容易写错编译不报错 IDE帮你检查不怕字段改名 │ └──────────────────────────────────────────────────────┘二、BaseMapper — 最底层的干活的一句话BaseMapper 就是你和数据库之间的直通车定义最基本的增删改查方法。// 你写的接口publicinterfaceUserMapperextendsBaseMapperUser{// 不用写任何代码BaseMapper 自带了// insert()、deleteById()、updateById()、selectById()// selectList()、selectPage() 等等}你需要知道的重点BaseMapper 里那些带条件的方法selectList、update、delete等参数都接收一个 Wrapper。Wrapper 就是条件构造器用来告诉数据库我要查/改/删哪些记录你不传 Wrapper → 查全表传了 Wrapper → 按条件筛选。// 不传条件 → 查全表userMapper.selectList(null);// 传条件 → 只查名字叫张三的userMapper.selectList(newQueryWrapperUser().eq(name,张三));三、IService — BaseMapper 的加装套餐一句话IService 不干新活它只是把 BaseMapper 包装了一下让你用起来更爽。// 你的 Service 接口publicinterfaceUserServiceextendsIServiceUser{}// 你的 Service 实现类ServicepublicclassUserServiceImplextendsServiceImplUserMapper,User// ← 这行绑定了 BaseMapperimplementsUserService{}IService 比 BaseMapper 多出来什么BaseMapper 的方法IService 多出来的方法insert(T entity)saveBatch(CollectionT)批量插入updateById(T entity)saveOrUpdate(T)有ID就更新没ID就插入selectList(Wrapper)list()直接查全表不用传 null 了返回int影响行数save()返回boolean成功/失败本质上ServiceImpl里面持有一个BaseMapperIService 所有的批量/便捷方法底层还是调的 BaseMapper。只是帮你省了循环和判断的代码。// 用 BaseMapper你得手动判断UseruseruserMapper.selectById(1L);if(usernull){userMapper.insert(newUser);}else{userMapper.updateById(newUser);}// 用 IService一行搞定userService.saveOrUpdate(newUser);四、QueryWrapper — 用字符串拼条件传统方式一句话把 SQL 的 WHERE 条件用 Java 代码拼出来列名写成字符串。QueryWrapperUserwrappernewQueryWrapper();wrapper.eq(name,张三)// WHERE name 张三.like(email,qq.com)// AND email LIKE %qq.com%.gt(age,18)// AND age 18.orderByDesc(create_time);// ORDER BY create_time DESCListUserusersuserMapper.selectList(wrapper);缺点很明显// 字段名写错了编译不报错运行时才发现wrapper.eq(naem,张三);// 应该是 name写成了 naem// 数据库字段改名了要全局搜索字符串容易漏掉wrapper.eq(create_time,...);// 如果改成了 gmt_create这里不会提示五、LambdaQueryWrapper — 用 Lambda 写列名推荐方式一句话跟 QueryWrapper 干一样的事但列名用实体类::get方法来写编译期就能检查错误。LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.eq(User::getName,张三)// 用 Lambda 引用字段.like(User::getEmail,qq.com).gt(User::getAge,18).orderByDesc(User::getCreateTime);ListUserusersuserMapper.selectList(wrapper);优点// 字段名写错了IDE 直接标红编译都过不了wrapper.eq(User::getNaem,张三);// 编译报错// 字段改名了用 IDE 的重构功能一键改名所有引用自动更新它怎么做到的Lambda 表达式User::getName在 Java 里是一种叫SFunction的东西MyBatis-Plus 会从里面解析出字段名name然后再拼 SQL。这个过程叫“序列化 Lambda 解析”。六、他们之间的调用关系用代码串一遍// 第 1 步定义实体 DataTableName(user)publicclassUser{privateLongid;privateStringname;privateIntegerage;privateStringemail;}// 第 2 步定义 Mapper继承 BaseMapper publicinterfaceUserMapperextendsBaseMapperUser{}// 第 3 步定义 Service继承 IService publicinterfaceUserServiceextendsIServiceUser{}ServicepublicclassUserServiceImplextendsServiceImplUserMapper,UserimplementsUserService{// ServiceImpl 内部自动绑定了 UserMapper}// 第 4 步在 Controller 里用 RestControllerpublicclassUserController{AutowiredprivateUserServiceuserService;// IService 层AutowiredprivateUserMapperuserMapper;// BaseMapper 层// 方式一用 BaseMapper LambdaQueryWrapperpublicListUsergetAdults(){LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.gt(User::getAge,18);returnuserMapper.selectList(wrapper);// BaseMapper 的方法}// 方式二用 IService 的便捷方法底层还是调 BaseMapperpublicListUsergetAdults2(){LambdaQueryWrapperUserwrappernewLambdaQueryWrapper();wrapper.gt(User::getAge,18);returnuserService.list(wrapper);// IService 的方法等价于上面}// 方式三用 IService 的链式调用LambdaQueryChainWrapperpublicListUsergetAdults3(){returnuserService.lambdaQuery().gt(User::getAge,18).list();// 连 Wrapper 都不用自己 new}}七、LambdaQueryChainWrapper — 最偷懒的写法如果你用 Service 层IService还可以更省事——链式调用// 不用自己 new LambdaQueryWrapperuserService.lambdaQuery().eq(User::getName,张三).gt(User::getAge,18).list();// 查列表userService.lambdaUpdate().eq(User::getName,张三).set(User::getAge,20).update();// 更新这个lambdaQuery()返回的就是一个LambdaQueryChainWrapper它帮你把LambdaQueryWrapper和BaseMapper的调用包在了一起你只管一直.下去就行了。八、总结什么时候用什么场景用什么原因简单单表 CRUD不用条件IService的save()、getById()等比 Mapper 多返回 boolean、批量操作带条件的查询/更新/删除LambdaQueryWrapper编译期检查字段名不怕写错用 Service 层 条件查询.lambdaQuery().xxx.list()最省代码链式一路点到底复杂 SQL多表 JOIN直接在 Mapper.xml 写 SQLWrapper 只适合单表多表老老实实写 SQL核心关系再捋一遍BaseMapper 数据库操作的底层接口方法参数用 Wrapper 传条件IService 包装了 BaseMapper加了批量/链式/布尔返回值的便捷方法QueryWrapper 用字符串写列名拼条件传统但容易出错LambdaQueryWrapper 用 Lambda 写列名拼条件编译期安全强烈推荐LambdaQueryChainWrapperlambdaQuery()返回的东西把 Wrapper Mapper 调用合成一条链写起来最爽一句话记牢IService 包着 BaseMapperBaseMapper 吃着 WrapperLambda 是 Wrapper 的升级版用 Lambda 代替字符串列名。

相关新闻