
文章目录1. 动态SQL1.1 if标签1.2 trim标签1.3 where标签1.4 set标签1.5 foreach标签1.6 include标签2. MyBatis-Plus3. MyBatis-Plus复杂操作3.1 常见注解3.1.1 TableName3.1.2 TableField3.1.3 TableId3.2 打印日志3.3 条件构造器3.3.1 QueryWrapper3.3.2 UpdateWrapper3.3.3 LambdaQueryWrapper3.3.4 LambdaUpdateWrapper1. 动态SQL动态 SQL 是Mybatis的强大特性之一能够完成不同条件下不同的 sql 拼接1.1 if标签可以用if标签来实现非必填字段比如性别 gender 为非必填字段接口定义IntegerinsertUserByCondition(Integergender);Xml实现insertidinsertUserByConditionINSERT into userinfo ( username, password, age,iftestgender ! nullgender,/ifphone) VALUES ( #{username}, #{password}, #{age},iftestgender ! null#{gender},/if#{phone})/insert或者使用注解方式, 但并不推荐, 感兴趣可自行了解test标签中的gender字段, 是传入对象的属性, 要跟Java对象的属性对应, 而不是数据库的字段不可以不判断直接把字段设置为null, 这种情况下, 如果gender字段有默认值, 就会设置为默认值1.2 trim标签之前的插入用户功能只是有一个 gender 字段可能是选填项如果有多个字段一般考虑使用标签结合标签对多个字段都采取动态生成的方式.prefix表示整个语句块以prefix的值作为前缀suffix表示整个语句块以suffix的值作为后缀prefixOverrides表示整个语句块要去除掉的前缀suffixOverrides表示整个语句块要去除掉的后缀insertidinsertUserByConditionINSERT INTO userinfotrimprefix(suffix)suffixOverrides,iftestusername !nullusername,/ififtestpassword !nullpassword,/ififtestage ! nullage,/ififtestgender ! nullgender,/ififtestphone ! nullphone,/if/trimVALUEStrimprefix(suffix)suffixOverrides,iftestusername !null#{username},/ififtestpassword !null#{password},/ififtestage ! null#{age},/ififtestgender ! null#{gender},/ififtestphone ! null#{phone}/if/trim/insert以上的sql,基于 prefix 配置开始部分加上 (基于 suffix 配置结束部分加上 )多个 组织的语句都以 , 结尾在最后拼接好的字符串还会以 , 结尾会基于suffixOverrides 配置去掉最后一个, 注意suffixOverrides 只能去掉末尾的逗号, 如果末尾不是, suffixOverrides不会做处理1.3 where标签需求: 传入的用户对象根据属性做where条件查询用户对象中属性不为 null 的都为查询条件.如:username 为 “a”则查询条件为 where username“a”每个条件前面都写 ANDwhere标签会自动去掉第一个 AND其他的保留ListUserInfoqueryByCondition(UserInfouserInfo);selectidqueryByConditionresultTypecom.example.test.demos.dao.UserInfoselect id, username, age, gender, phone, delete_flag, create_time, update_time from userinfowhereiftestage ! nulland age #{age}/ififtestgender ! nulland gender #{gender}/ififtestdeleteFlag ! nulland delete_flag #{deleteFlag}/if/where/select注意语句中数据库字段和Java对象字段的映射关系1.4 set标签需求: 根据传入的用户对象属性来更新用户数据可以使用标签来指定动态内容接口定义: 根据传入的用户 id 属性修改其他不为 null 的属性IntegerupdateUserByCondition(UserInfouserInfo);updateidupdateUserByConditionsetiftestusername ! nullusername #{username}/ififtestage ! nullage #{age},/ififtestdeleteFlag ! nulldelete_flag #{deleteFlag},/if/setwhere id #{id}/updateset 动态的在SQL语句中插入set关键字并会删掉额外的逗号. (用于update语句中) 以上标签也可以使用 trim prefix“set” suffixOverrides“,” 替换用if标签也能实现, 但是需要处理边界情况和多出来逗号, 很麻烦1.5 foreach标签对集合进行遍历时可以使用该标签。标签有如下属性:collection绑定方法参数中的集合如 ListSetMap或数组对象item遍历时的每一个对象open语句块开头的字符串close语句块结束的字符串separator每次遍历之间间隔的字符串接口定义: 根据多个userid, 删除用户数据voiddeleteByIds(Param(ids)ListIntegerids);XML实现deleteiddeleteByIdsdelete from userinfo where id inforeachcollectionidsitemidseparator,open(close)#{id}/foreach/delete形参如果是多个集合, 需要用Param, 否则会报错, 用了Param后, collection的值要和param中写的一致1.6 include标签在xml映射文件中配置的SQL有时可能会存在很多重复的片段此时就会存在很多冗余的代码我们可以对重复的代码片段进行抽取将其通过 sql 标签封装到一个SQL片段然后再通过include 标签进行引用sql定义可重用的SQL片段include通过属性refid指定包含的SQL片段通过sql定义重复SQL片段sqlidallColumnid, username, age, gender, phone, delete_flag, create_time, update_time/sql通过 include 标签在原来抽取的地方进行引用selectidqueryAllUserresultMapBaseMapselectincluderefidallColumn/includefrom userinfo/select2. MyBatis-PlusMyBatis-Plus(简称 MP) 是一个 MyBatis 的增强工具, 在 MyBatis 的基础上只做增强不做改变, 为简化开发. 提高效率而生。MybatisPlus提供了一个基础的 BaseMapper 接口已经实现了单表的CRUD, 我们自定义的Mapper只需要继承这个BaseMapper, 就无需自己实现单表CRUDMapperpublicinterfaceUserInfoMapperextendsBaseMapperUserInfo{}UserInfoMapper 在继承 BaseMapper 时, 指定了一个泛型, 这个UserInfo就是与数据库表相对应的实体类默认情况下:表名: 实体类的驼峰表示法转换成蛇形表示法(下划线分割), 作为表名. 比如UserInfo - user_info字段: 根据实体类的属性名, 转换为蛇形表示法作为字段名. 比如deleteFlag - delete_flag主键: 默认为id3. MyBatis-Plus复杂操作3.1 常见注解3.1.1 TableName我们可以通过 TableName 来标识实体类对应的表DataTableName(user_info)publicclassUserInfo{privateIntegerid;privateStringusername;privateStringpassword;privateIntegerage;privateIntegergender;privateStringphone;privateIntegerdeleteFlag;privateDatecreateTime;privateDateupdateTime;}3.1.2 TableField我们可以通过 TableField 来标识 对应的字段名DataTableName(user_info)publicclassUserInfo{privateIntegerid;privateStringusername;privateStringpassword;privateIntegerage;privateIntegergender;privateStringphone;TableField(delete_flag)privateIntegerdeleteFlag;privateDatecreateTime;privateDateupdateTime;}3.1.3 TableId我们可以通过 TableId 来 指定对应的主键DataTableName(user_info)publicclassUserInfo{TableId(id)privateIntegerid;privateStringusername;privateStringpassword;privateIntegerage;privateIntegergender;privateStringphone;TableField(delete_flag)privateIntegerdeleteFlag;privateDatecreateTime;privateDateupdateTime;}如果属性名和字段名不一致, 需要在 TableId 指明对应的字段名;属性名和字段一致的情况下, 直接加 TableId 注解就可以3.2 打印日志Mybatis-Plus配置日志如下:mybatis-plus:configuration:# 配置打印 MyBatis日志log-impl:org.apache.ibatis.logging.stdout.StdOutImpl3.3 条件构造器入门程序里的使用, 都是简单的CRUD, 在实际的应用场景中, 我们还需要使用更复杂的操作, MyBatisPlus 也给我们提供了相应的支持 MyBatis-Plus 提供了一套强大的条件构造器(Wrapper), 用于构建复杂的数据库查询条件. Wrapper 类 允许开发者以链式调用的方式构造查询条件, 无需编写繁琐的 SQL 语句, 从而提高开发效率并减少 SQL注入 的风险以下是主要的 Wrapper 类及其功能AbstractWrapper这是一个抽象基类, 提供了所有 Wrapper 类共有的方法和属性.QueryWrapper用于构造查询条件, 在AbstractWrapper的基础上拓展了一个select方法, 允许指定查询字段UpdateWrapper: 用于构造更新条件, 可以在更新数据时指定条件LambdaQueryWrapper:基于 Lambda 表达式的查询条件构造器, 它通过 Lambda 表达式来引用实体类的属性从而避免了硬编码字段名LambdaUpdateWrapper: 基于 Lambda 表达式的更新条件构造器, 它允许你使用 Lambda 表达式来指定更新字段和条件同样避免了硬编码字段名的问题LambdaQueryWrapper和LambdaUpdateWrapper是能完全替代QueryWrapper和UpdateWrapper的, 而且也更推荐使 lambdaWrapper3.3.1 QueryWrapperQueryWrapper并不只用于查询语句, 无论是修改, 删除, 查询, 都可以使用QueryWrapper来构建查询条件这里只简单介绍查询和更新SELECTid,username,password,ageFROMuser_infoWHEREage18ANDusername%min%voidtestQueryWrapper(){QueryWrapperUserInfouserInfoQueryWrappernewQueryWrapperUserInfo().select(id,username,password,age).eq(age,18).like(username,min);ListUserInfouserInfosuserInfoMapper.selectList(userInfoQueryWrapper);}QueryWrapper并不只用于查询语句, 无论是修改, 删除, 查询, 都可以使用QueryWrapper来构建查询条件这里只简单介绍查询和更新UPDATEuser_infoSETdelete_flag?WHEREage20voidtestUpdateByQueryWrapper(){QueryWrapperUserInfouserInfoQueryWrappernewQueryWrapperUserInfo().lt(age,20);UserInfouserInfonewUserInfo();userInfo.setDeleteFlag(1);userInfoMapper.update(userInfo,userInfoQueryWrapper);}• lt : “less than” 的缩写表示小于.• le : less than or equal to的缩写, 表示小于等于• ge : “greater than or equal to” 的缩写, 表示大于等于.• gt : “greater than” 的缩写, 表示大于.• eq : “equals” 的缩写, 表示等于.• ne : “not equals” 的缩写, 表示不等于.3.3.2 UpdateWrapper对于更新, 我们也可以直接使用 UpdateWrapper, 在不创建实体对象的情况下, 直接设置更新字段和条件UPDATEuser_infoSETdelete_flag0,age5WHEREidIN(1,2,3)voidtestUpdateByUpdateWrapper(){UpdateWrapperUserInfoupdateWrappernewUpdateWrapperUserInfo().set(delete_flag,0).set(age,5).in(id,List.of(1,2,3));userInfoMapper.update(updateWrapper);}QueryWrapper 和 UpdateWrapper存在一个问题, 就是需要写死字段名, 如果字段名发生变更, 可能会因为测试不到位导致出错;MyBatis-Plus 给我们提供了一种基于Lambda表达式的条件构造器, 它通过 Lambda 表达式来引用实体类的属性从而避免了硬编码字段名, 也提高了代码的可读性和可维护性3.3.3 LambdaQueryWrappervoidtestLambdaQueryWrapper(){QueryWrapperUserInfoqueryWrappernewQueryWrapperUserInfo();queryWrapper.lambda().select(UserInfo::getUsername,UserInfo::getPassword,UserInfo::getAge).eq(UserInfo::getId,1);userInfoMapper.selectList(queryWrapper);}3.3.4 LambdaUpdateWrappervoidtestLambdaUpdateWrapper(){UpdateWrapperUserInfoupdateWrappernewUpdateWrapperUserInfo();updateWrapper.lambda().set(UserInfo::getDeleteFlag,0).set(UserInfo::getAge,5).in(UserInfo::getId,List.of(1,2,3));userInfoMapper.update(updateWrapper);}