Mybatis 进阶 / Mybatis—Puls (详细)

目录

一.动态SQL

1.1标签

1.2 标签

 1.3标签

 1.4标签

 1.5标签

1.6标签 

mybatis总结:

 二.Mybatis-Puls

 2.1准备工作

2.2CRUD单元测试

2.2.1创建UserInfo实体类

2.2.2编写Mapper接⼝类

2.2.3 测试类

2.3 常见注解

 2.3.1@TableName

  2.3.2@TableField

2.4打印日志 

 2.5条件构造器

 2.5.1QueryWrapper

查询操作

更新 

 删除

 2.5.2UpdateWrapper

2.5.3LambdaQueryWrapper

2.5.4 LambdaUpdateWrapper

 2.6⾃定义SQL

示例1:

示例二 XML的⽅式完成

示例三:使用注解的方式

MyBatis-Plus总结:


 可以先回顾一下初识Mybatis

 

一.动态SQL

动态 SQL 是Mybatis的强⼤特性之⼀,能够完成不同条件下不同的 sql 拼接可以

参考官方文档:MyBatis动态sql

熟悉使用各种标签

1.1<if>标签

在注册信息的时候,可能会遇到这种问题,如图:

 

注册分为两种字段:必填字段和⾮必填字段,那如果在添加⽤⼾的时候有不确定的字段传⼊,程序应 该如何实现呢?
这个时候就需要使⽤动态标签 来判断了,⽐如添加的时候性别 gender 为⾮必填字段,具体实现如 下

Mapper接⼝定义: 

@Mapper
public interface UserInfoXmlMapper {Integer insertUserByCondition(UserInfo userInfo);}

 Mapper.xml实现:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatis.mapper.UserInfoXmlMapper"><insert id="insertUserByCondition">INSERT INTO user_info(username,`password`,age,<if test="gender != null">gender,</if>phone)VALUES (#{username},#{age},<if test="gender != null">#{gender},</if>#{phone})</insert>
</mapper>

 

注解⽅式(不推荐) 

把上⾯SQL(包括标签), 使⽤ <script></script> 标签括起来就可以
@Insert("<script>" +"INSERT INTO userinfo (username,`password`,age," +"<if test='gender!=null'>gender,</if>" +"phone)" +"VALUES(#{username},#{age}," +"<if test='gender!=null'>#{gender},</if>" +"#{phone})"+"</script>")
Integer insertUserByCondition(UserInfo userInfo);
注意 test 中的 gender,是传⼊对象中的属性,不是数据库字段
问: 可不可以不进⾏判断, 直接把字段设置为null呢?
答: 不可以, 这种情况下, 如果gender字段有默认值, 就会设置为默认值

测试代码:

@Testvoid insertUserByCondition() {UserInfo userInfo = new UserInfo();userInfo.setUsername("cuihua");userInfo.setPassword("cuihua");userInfo.setAge(23);userInfo.setPhone("11111111111");System.out.println(userInfoXmlMapper.insertUserByCondition(userInfo));}

 测试结果:

1.2<trim> 标签

之前的插⼊⽤⼾功能,只是有⼀个 gender 字段可能是选填项,如果有多个字段,⼀般考虑使⽤标签结 合标签,对多个字段都采取动态⽣成的⽅式。
标签中有如下属性:
  • prefix:表⽰整个语句块,以prefix的值作为前缀
  • suffix:表⽰整个语句块,以suffix的值作为后缀
  • prefixOverrides:表⽰整个语句块要去除掉的前缀
  • suffixOverrides:表⽰整个语句块要去除掉的后缀

 调整后的.XML代码:

<insert id="insertUserByCondition">INSERT INTO user_info<trim prefix="(" suffix=")" suffixOverrides=","><if test="username !=null">username,</if><if test="password !=null">`password`,</if><if test="age != null">age,</if><if test="gender != null">gender,</if><if test="phone != null">phone,</if></trim>VALUES<trim prefix="(" suffix=")" suffixOverrides=","><if test="username !=null">#{username},</if><if test="password !=null">#{password},</if><if test="age != null">#{age},</if><if test="gender != null">#{gender},</if><if test="phone != null">#{phone}</if></trim></insert>
使⽤注解⽅式(不推荐)
 @Insert("<script>" +"INSERT INTO user_info " +"<trim prefix='(' suffix=')' suffixOverrides=','>" +"<if test='username!=null'>username,</if>" +"<if test='password!=null'>password,</if>" +"<if test='age!=null'>age,</if>" +"<if test='gender!=null'>gender,</if>" +"<if test='phone!=null'>phone,</if>" +"</trim>" +"VALUES " +"<trim prefix='(' suffix=')' suffixOverrides=','>" +"<if test='username!=null'>#{username},</if>" +"<if test='password!=null'>#{password},</if>" +"<if test='age!=null'>#{age},</if>" +"<if test='gender!=null'>#{gender},</if>" +"<if test='phone!=null'>#{phone}</if>" +"</trim>"+"</script>")Integer insertUserByCondition1(UserInfo userInfo);

 在以上 sql 动态解析时,会将第⼀个 部分做如下处理:

  • 基于 prefix 配置,开始部分加上 (
  • 基于 suffix 配置,结束部分加上 )
  • 多个 组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于 suffixOverrides 配置去掉最后⼀个 ,
  • 注意 <if test="username !=null"> 中的 username 是传⼊对象的属性

 1.3<where>标签

需求: 传⼊的⽤⼾对象,根据属性做where条件查询,⽤⼾对象中属性不为 null 的,都为查询条件. 例如 username 为 "a",则查询条件为 where username="a"
Mapper接口代码:
@Mapper
public interface UserInfoXmlMapper {List<UserInfo> selecetByCondition(UserInfo userInfo);
}

.XML代码实现:

  <select id="selecetByCondition" resultType="com.example.mybatis.model.UserInfo">select * from user_info<where><if test="username != null">username = #{username}</if><if test="password != null">password = #{password}</if></where></select>
<where> 只会在⼦元素有内容的情况下才插⼊where⼦句,⽽且会⾃动去除⼦句的开头的AND或 OR

测试代码:

 查询条件我只写了一个,可以写多个的

 @Testvoid selecetByCondition() {UserInfo userInfo = new UserInfo();userInfo.setUsername("wangwu");System.out.println(userInfoXmlMapper.selecetByCondition(userInfo));}

测试结果:

 1.4<set>标签

需求: 根据传⼊的⽤⼾对象属性来更新⽤⼾数据,可以使⽤标签来指定动态内容
接⼝定义: 根据传⼊的⽤⼾ id 属性,修改其他不为 null 的属性
@Mapper
public interface UserInfoXmlMapper {Integer updateByCondition(UserInfo userInfo);
}

.XML代码实现:

<update id="updateByCondition">update user_info<set><if test="username != null" >username = #{username},</if><if test="password != null" >password = #{password},</if><if test="age != null" >age = #{age}</if></set>where id = #{id}</update>

测试代码:

目的把ID为  '1' 的名字改为 "tietui" ,并打印

   @Testvoid updateByCondition() {UserInfo userInfo = new UserInfo();userInfo.setUsername("tietui");userInfo.setId(1);System.out.println(userInfoXmlMapper.updateByCondition(userInfo));}

测试结果:

 <set> :动态的在SQL语句中插⼊set关键字,并会删掉额外的逗号. (⽤于update语句中)

 1.5<foreach>标签

对集合进⾏遍历时可以使⽤该标签。标签有如下属性:
  • collection:绑定⽅法参数中的集合,如 List,Set,Map或数组对象
  • item:遍历时的对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的字符串

需求目的: 根据多个userid, 删除⽤⼾数据 

接口方法实现:

@Mapper
public interface UserInfoXmlMapper {Integer delete(List<Integer> list);
}

.XML代码实现:

    <delete id="delete">delete from user_infowhere id in<foreach collection="list" item="id" separator="," open="(" close=")">#{id}</foreach></delete>

测试代码:

    @Testvoid Delete() {List<Integer> list =new ArrayList<>();list.add(5);list.add(8);System.out.println(userInfoXmlMapper.delete(list));}

测试结果:

 

1.6<include>标签 

就是直接对需要的代码进⾏抽取,将其通过 <sql> 标签封装到⼀个SQL⽚段,然后再通过 <include> 标签进⾏引⽤
  • <sql> :定义可重⽤的SQL⽚段
  • <include> :通过属性refid,指定包含的SQL⽚段
例如:
可能会多次使用这个sql片段 ,就可以加入<sql>标签完成复用
<sql id="allColumn">id, username, age, gender, phone, delete_flag, create_time, update_time
</sql>
通过 <include> 标签在原来抽取的地⽅进⾏引⽤。操作如下:
 <select id="queryById" resultType="com.example.mybatis.model.UserInfo">select<include refid="allColumn"></include>from userinfo where id= #{id}</select>

mybatis总结:

  • 学习了MyBatis动态SQL的⼀些标签使⽤. <if>标签中, 使⽤的是Java对象的属性, ⽽⾮数据库字段.
  • 动态SQL的实现, 注解和xml的实现⽅式相似, 区别是注解⽅式需要添加 <script></script> .
  • 但是使⽤注解的⽅式时, Idea不会进⾏格式检测, 容易出错, 建议使⽤xml的⽅式

 二.Mybatis-Puls

MyBatis-Plus(简称 MP) 是⼀个 MyBatis 的增强⼯具, 在 MyBatis 的基础上只做增强不做改变, 为简化开 发. 提⾼效率⽽⽣

特性:

  • 润物⽆声: 只做增强不做改变,引⼊它不会对现有⼯程产⽣影响,如丝般顺滑.
  • 效率⾄上: 只需简单配置,即可快速进⾏单表 CRUD 操作,从⽽节省⼤量时间.
  • 丰富功能: 代码⽣成、⾃动分⻚、逻辑删除、⾃动填充、拦截器等功能⼀应俱全.
  • ⼴泛认可: 连续 5 年获得开源中国年度最佳开源项⽬殊荣,Github 累计 16K Star.

⽀持数据库:

PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, OceanBase, H2, DB2...
(任何能使⽤ MyBatis 进⾏增删改查,并且⽀持标准 SQL 的数据库应该都在 MyBatis-Plus 的⽀持范围内)

 官方网址:MyBatis-Puls 为简化开发而生

 Mybatis-Plus操作数据库的步骤:

  1. 准备⼯作(数据准备, 项⽬准备, 引⼊依赖, 配置数据库连接信息)
  2. 编码(数据库表对应的实体类, 以及数据操作的Mapper⽂件)
  3. 测试

 2.1准备工作

创建数据库 ➡️ 创建表(例如用户表) ➡️ 创建对应的实体类User

 与Mybatis一样:

  •        创建springboot项目
  •         添加MyBatis-Plus和MySQL依赖, 配置数据库连接信息

添加 MyBatis-Plusy依赖

    <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.9</version></dependency>

 添加 MySQL依赖 

        <dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency>

 .yml文件配置:

# 数据库连接配置
spring:datasource:#数据库连接的urlurl: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false#连接数据库的⽤⼾名username: root#连接数据库的⽤⼾名password: 123456driver-class-name: com.mysql.cj.jdbc.Drivermybatis-plus:# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件mapper-locations: classpath:mybatis/**Mapper.xml# 配置打印 MyBatis日志configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #配置驼峰⾃动转换

2.2CRUD单元测试

2.2.1创建UserInfo实体类

       实体类的属性名与表中的字段名一一对应

package com.example.mybatisplus.mode;import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.util.Date;@Data
@TableName("user_info")
public class UserInfo {@TableIdprivate Integer id;@TableField("username")private String username ;private String password;private Integer age;private Integer gender;private String phone;private Integer deleteFlag;private Date createTime;private Date updateTime;
}

2.2.2编写Mapper接⼝类

MybatisPlus提供了⼀个基础的 BaseMapper 接⼝,已经实现了单表的CRUD, 我们⾃定义的
Mapper只需要继承这个BaseMapper, 就⽆需⾃⼰实现单表CRUD了
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {}
也可以在启动类上添加 @MapperScan , 扫描Mapper⽂件夹, ⼆选⼀即可.

2.2.3 测试类

在创建出来的SpringBoot⼯程中,在src下的test⽬录下,已经⾃动帮我们创建好了测试类 ,我们可以 直接使⽤这个测试类来进⾏测试

测试基本的CRUD功能 :

package com.example.mybatisplus;import com.example.mybatisplus.mapper.UserInfoMapper;
import com.example.mybatisplus.mode.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest
class MybatisPlusApplicationTests {@AutowiredUserInfoMapper userInfoMapper;@Testvoid contextLoads() {System.out.println(userInfoMapper.selectById(1));}@Testvoid testInsert() {UserInfo user = new UserInfo();user.setUsername("bite");user.setPassword("123456");user.setAge(11);user.setGender(0);user.setPhone("18610001234");userInfoMapper.insert(user);}@Testvoid testSelectById() {UserInfo user = userInfoMapper.selectById(1L);System.out.println("user: " + user);}@Testvoid testSelectByIds() {List<UserInfo> users = userInfoMapper.selectBatchIds(List.of(1L, 2L, 3L,4L));users.forEach(System.out::println);}@Testvoid testUpdateById() {UserInfo user = new UserInfo();user.setId(1);user.setPassword("4444444");userInfoMapper.updateById(user);}
}

 

2.3 常见注解

在上⾯的程序中, MyBatis是如何知道, 我们要操作的是哪张表, 表⾥有哪些字段呢?
看下咱们Mapper的代码:
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {}
UserInfoMapper 在继承 BaseMapper 时, 指定了⼀个泛型, 这个UserInfo就是与数据库表相对应的实体类.
MyBatis-Plus会根据这个实体类来推断表的信息.
默认情况下:
  1. 表名: 实体类的驼峰表⽰法转换成蛇形表⽰法(下划线分割), 作为表名. ⽐如UserInfo -> user_info
  2. 字段: 根据实体类的属性名 转换为蛇形表⽰法作为字段名. ⽐如deleteFlag -> delete_flag
  3. 主键: 默认为id

 2.3.1@TableName

修改实体类名UserInfo为 Userinfo
运⾏结果:

从⽇志可以看到, 默认查找的表名为userinfo 

可以通过 @TableName 来标识实体类对应的表
@Data
@TableName("user_info")
public class UserInfo {@TableIdprivate Integer id;private String username ;private String password;private Integer age;private Integer gender;private String phone;@TableField("delete_flag")private Integer deleteFlag;private Date createTime;private Date updateTime;
}

  2.3.2@TableField

修改属性名 deleteFlag 为 deleteflag
运⾏结果:

 ⽇志可以看到, 根据属性名转换前的字段名为: deleteflag

可以通过 @TableField 来标识 对应的字段名

 

@Data
@TableName("user_info")
public class UserInfo {@TableIdprivate Integer id;private String username ;private String password;private Integer age;private Integer gender;private String phone;@TableField("delete_flag")private Integer deleteFlag;private Date createTime;private Date updateTime;
}

2.3.3 @TableId 

修改属性名 id 为 userId 

运⾏结果:

 

可以通过 @TableId 来 指定对应的主键 

@Data
@TableName("user_info")
public class UserInfo {@TableIdprivate Integer id;private String username ;private String password;private Integer age;private Integer gender;private String phone;@TableField("delete_flag")private Integer deleteFlag;private Date createTime;private Date updateTime;
}
如果属性名和字段名不⼀致, 需要在 @TableId 指明对应的字段名
属性名和字段⼀致的情况下, 直接加 @TableId 注解就可以.

2.4打印日志 

添加文件配置即可

mybatis-plus:# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件mapper-locations: classpath:mybatis/**Mapper.xml# 配置打印 MyBatis日志configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true #配置驼峰⾃动转换

 2.5条件构造器

⼊⻔程序⾥的使⽤, 都是简单的CRUD, 在实际的应⽤场景中, 我们还需要使⽤更复杂的操作, MyBatisPlus 也给我们提供了相应的⽀持.

MyBatis-Plus 提供了⼀套强⼤的条件构造器(Wrapper), ⽤于构建复杂的数据库查询条件. Wrapper 类允许开发者以链式调⽤的⽅式构造查询条件, ⽆需编写繁琐的 SQL 语句, 从⽽提⾼开发效率并减少 SQL 注⼊的⻛险

以下是主要的 Wrapper 类及其功能:

  • AbstractWrapper:这是⼀个抽象基类, 提供了所有 Wrapper 类共有的⽅法和属性. 详细参考官⽹ 介绍: 条件构造器
  • QueryWrapper:⽤于构造查询条件, 在AbstractWrapper的基础上拓展了⼀个select⽅法, 允许指 定查询字段.
  • UpdateWrapper: ⽤于构造更新条件, 可以在更新数据时指定条件.
  • LambdaQueryWrapper:基于 Lambda 表达式的查询条件构造器, 它通过 Lambda 表达式来引⽤ 实体类的属性,从⽽避免了硬编码字段名.
  • LambdaUpdateWrapper: 基于 Lambda 表达式的更新条件构造器, 它允许你使⽤ Lambda 表达 式来指定更新字段和条件,同样避免了硬编码字段名的问题

 2.5.1QueryWrapper

QueryWrapper并不只⽤于查询语句, ⽆论是修改, 删除, 查询, 都可以使⽤QueryWrapper来构建查询条件.
查询操作

完成下述SQL查询:

SELECT id,username,password,age FROM user_info WHERE age = 18 AND username 
"%min%"

测试代码:

  @Testvoid testQueryWrapper(){QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>().select("id","username","password","age").eq("age",18).like("username", "min");List<UserInfo> userInfos = userInfoMapper.selectList(userInfoQueryWrapper);userInfos.forEach(System.out::println);}

 注意:

默认情况下Mybatis-Plus会根据 @TableFiled ⽣成别名, 当指定了QueryWrapper的select属性后
就仅仅是属性值⽽没有了别名. 查询出来的结果会对应不上

解决办法:

  1. ⾃⼰写⾃定义SQL
  2. 实体类名和字段名保持⼀致
  3. 不指定QueryWrapper的select字段
  4. 使⽤LambdaQueryWrapper实现
更新 
完成下述SQL查询操作:
UPDATE user_info SET delete_flag=? WHERE age < 20
测试代码:
  @Testvoid testUpdateByQueryWrapper(){QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>().lt("age", 20);UserInfo userInfo = new UserInfo();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" 的缩写, 表⽰不等于
 删除

 完成下述SQL查询

DELETE FROM user_info WHERE age = 18

测试代码:

 @Testvoid testDeleteByQueryWrapper(){QueryWrapper<UserInfo> userInfoQueryWrapper = new QueryWrapper<UserInfo>().eq("age",18);userInfoMapper.delete(userInfoQueryWrapper);}

 2.5.2UpdateWrapper

对于更新, 我们也可以直接使⽤ UpdateWrapper, 在不创建实体对象的情况下, 直接设置更新字段和条 件.
基础更新:
完成下述SQL查询:
UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)

测试代码:

 @Testvoid testUpdateByUpdateWrapper(){UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>().set("delete_flag",0).set("age", 5).in("id", List.of(1,2,3));userInfoMapper.update(updateWrapper);}

 

基于SQL更新:
完成下述SQL查询:
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)

测试代码:

 @Testvoid testUpdateBySQLUpdateWrapper(){UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>().setSql("age = age+10").in("id", List.of(1,2,3));userInfoMapper.update(updateWrapper);}

2.5.3LambdaQueryWrapper

QueryWrapper 和 UpdateWrapper存在⼀个问题, 就是需要写死字段名, 如果字段名发⽣变更, 可能会 因为测试不到位酿成事故.
MyBatis-Plus 给我们提供了⼀种基于Lambda表达式的条件构造器, 它通过 Lambda 表达式来引⽤实体 类的属性,从⽽避免了硬编码字段名, 也提⾼了代码的可读性和可维护性
  • LambdaQueryWrapper
  • LambdaUpdateWrapper

分别对应上述的QueryWrapper和UpdateWrapper 

 具体使用:

@Testvoid testLambdaQueryWrapper(){QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();queryWrapper.lambda().select(UserInfo::getUsername, UserInfo::getPassword,UserInfo::getAge).eq(UserInfo::getUserId, 1);userInfoMapper.selectList(queryWrapper).forEach(System.out::println);}

 

2.5.4 LambdaUpdateWrapper

LambdaUpdateWrapper⽤法和 LambdaQueryWrapper相似
@Testvoid testLambdUpdateByUpdateWrapper(){UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();updateWrapper.lambda().set(UserInfo::getDeleteFlag, 0).set(UserInfo::getAge, 5).in(UserInfo::getUserId, List.of(1,2,3));userInfoMapper.update(updateWrapper);}

 2.6⾃定义SQL

在实际的开发中, MyBatis-Plus提供的操作不能满⾜我们的实际需求, MyBatis-Plus 也提供了⾃定义 SQL的功能, 我们可以利⽤Wrapper构造查询条件, 再结合Mapper编写SQL

要使用自定义SQL的功能  MyBatis-Plus版本号不得低于 3.0.7

示例1:

完成下述SQL查询

select id,username,password,age FROM user_info WHERE username = "admin"

Mappe接口代码: 

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {@Select("select id,username,password,age FROM user_info ${ew.customSqlSegment}")List<UserInfo> queryUserByCustom(@Param(Constants.WRAPPER)Wrapper<UserInfo> wrapper);
}
测试代码:
@SpringBootTest
class UserInfoMapperTest {@AutowiredUserInfoMapper userInfoMapper;@Testvoid queryUserByCustom() {QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().eq("username","admin");userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);}
}
注意事项:
  • 参数命名:在⾃定义 SQL 时, 传递 Wrapper 对象作为参数时, 参数名必须为 ew ,或者使⽤注解 @Param(Constants.WRAPPER) 明确指定参数为 Wrapper 对象.
  • 使⽤ ${ew.customSqlSegment} :在 SQL 语句中,使⽤ ${ew.customSqlSegment} 引⽤ Wrapper 对象⽣成的 SQL ⽚段.
  • 不⽀持基于 entity 的 where 语句:⾃定义 SQL 时,Wrapper 对象不会基于实体类⾃动⽣成 where ⼦句,你需要⼿动编写完整的 SQL 语句

示例二 XML的⽅式完成

MyBatis-Plus 在 MyBatis 的基础上只做增强不做改变, 所以也⽀持XML的实现⽅式

上述功能也可以使⽤XML的⽅式完成

1.配置mapper路径 :

mybatis-plus:mapper-locations: "classpath*:/mapper/**.xml" # Mapper.xml

2.mapper接口方法:

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {List<UserInfo> queryUserByCustom(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
}

3.编写XML:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatisplus.mapper.UserInfoMapper"><select id="queryUserByCustom" resultType="com.example.mybatisplus.mode.UserInfo">select * from user_info ${ew.customSqlSegment}</select>
</mapper>

4.测试

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mybatisplus.mode.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserInfoMapperTest {@AutowiredUserInfoMapper userInfoMapper;@Testvoid queryUserByCustom() {QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().eq("userName","lisi");userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);}
}

测试结果:

 示例三:使用注解的方式

完成下述SQL查询
UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)

mapper接口方法:

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {@Update("UPDATE user_info SET age = age+ #{addAge} ${ew.customSqlSegment}")void updateUserByCustom(@Param("addAge") int addAge, @Param("ew")Wrapper<UserInfo> wrapper);
}
测试代码:
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.mybatisplus.mode.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserInfoMapperTest {@AutowiredUserInfoMapper userInfoMapper;@Testvoid updateUserByCustom() {QueryWrapper<UserInfo> queryWrapper =new QueryWrapper<UserInfo>().in("id", List.of(1,2,3));//目的把id为1,2,3  在原先年龄的基础上加10userInfoMapper.updateUserByCustom(10,queryWrapper);}
}

测试结果:

MyBatis-Plus总结:

  • MyBatis-Plus 是 MyBatis 的增强⼯具, 在 MyBatis 的基础上只做增强不做改变, 可以⽤更少的代码实现数据库表的CRUD, 让我们的开发变得更加简单
  • MyBatis-Plus ⽀持⾃定义SQL, 版本不低于3.0.7, 传递 Wrapper 对象作为参数时, 参数名必须为 ew,在 SQL 语句中,使⽤ ${ew.customSqlSegment} 来引⽤ Wrapper 对象⽣成的 SQL ⽚段

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/3363.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025.1.16——三、supersqli 绕过|堆叠注入|handler查询法|预编译绕过法|修改原查询法

题目来源&#xff1a;攻防世界supersqli 目录 一、打开靶机&#xff0c;整理已知信息 二、sqlmap解题 step 1&#xff1a;爆数据库 step 2&#xff1a;爆表 二、手工注入解题 step 1&#xff1a;判断注入类型 step 2&#xff1a;判断字段数 step 3&#xff1a;查询数据…

【数据库初阶】MySQL中表的约束(上)

??博主首页&#xff1a; ??专栏首页&#xff1a; 数据库初阶 ??其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们&#xff0c;大家好&#xff01;在这篇文章中&#xff0c;我们将深入浅出地为大家讲解 MySQL中表的约束 帮助您轻松入门&#xff0c;快…

HTML基础与实践

目录 HTML 结构 认识 HTML 标签 HTML 文件基本结构 标签层次结构 快速生成代码框架 HTML 常见标签 注释标签 标题标签: h1-h6 段落标签: p 换行标签: br 格式化标签 图片标签: img 超链接标签: a ​编辑链接的几种形式: 表格标签 基本使用 合并单元格 …

初识go语言之指针用法

一、环境准备 安装go语言编译环境&#xff0c;官网地址&#xff1a;https://go.dev/dl/ 或者 https://golang.google.cn/dl/ 点击下载按提示安装即可 vscode 安装go语言扩展 测试 package mainimport "fmt"func main() {fmt.Println("Hello, World!") …

mac 安装 node

brew versions node // 安装 node brew versions node14 // 安装指定版本 卸载node: sudo npm uninstall npm -g sudo rm -rf /usr/local/lib/node /usr/local/lib/node_modules /var/db/receipts/org.nodejs.* sudo rm -rf /usr/local/include/node /Users/$USER/.npm su…

2025.1.16——六、BabySQL 双写绕过|联合注入

题目来源&#xff1a;buuctf [极客大挑战 2019]BabySQL 1 目录 一、打开靶机&#xff0c;分析已知信息 二、手工注入解题 step 1&#xff1a;万能密码 step 2&#xff1a;正常注入&#xff0c;判断字段数 step 3&#xff1a;绕过 step 4&#xff1a;查数据库 step 5&am…

第4章 Kafka核心API——Kafka客户端操作

Kafka客户端操作 一. 客户端操作1. AdminClient API 一. 客户端操作 1. AdminClient API

浅谈云计算21 | Docker容器技术

Docker容器技术 一、 容器技术特性1.1 轻量级特性1.2 隔离性特性 二、容器镜像2.1 容器镜像概述2.1.1 定义与构成2.1.2 分层结构 2.2 联合文件系统2.3 容器镜像的构建与管理2.3.1 容器镜像的构建2.3.2 **构建镜像流程**2.3.3 **应用场景**2.3.4 镜像仓库的应用 2.4 容器镜像的优…

Android CustomTextField

在 Compose 中开发用户界面时&#xff0c;需要处理输入框和键盘的交互&#xff0c;例如在键盘弹出时调整布局位置&#xff0c;避免遮挡重要内容。本篇博客将通过一个完整的示例展示如何实现这一功能。 功能概述 本例实现了一个简单的输入框。当输入框获得焦点或输入文字时&…

[0242].第4-3章:SpringBoot2核心技术笔记

Java学习大纲 1、笔记 第1步&#xff1a;框架初识 [0242-01].第01节&#xff1a;SpringBoot初识 第2步&#xff1a;入门项目 [0242-02].第02节&#xff1a;SpringBoot入门项目[0242-03].第03节&#xff1a;SpringBoot开发技巧 第3步&#xff1a;开发应用 配置文件&#xff1a…

2025.1.15——四、布尔注入

题目来源&#xff1a;ctfhub技能树 目录 一、基本操作&#xff1a;整理已知信息&#xff0c;得到本题为布尔注入 方法一&#xff1a;手工盲注&#xff08;不推荐&#xff09; step 1&#xff1a;判断具体形式 step 2&#xff1a;查询字段数 step 3&#xff1a;通过回显判…

Vue2.0的安装

1.首先查看是否已经安装了node.js 选择以管理员方式打开命令提示符&#xff08;权限较高&#xff09;&#xff0c;或者通过cmd的方式打开 打开后输入node -v 查看自己电脑是否安装node&#xff0c;以及版本号 node -v 如果没有的话&#xff0c;请查看Node.js的安装 2.Vue和脚…

SQL Server 导入Excel数据

1、选中指定要导入到哪个数据库&#xff0c;右键选择 》任务 》导入数据 2、数据源 选择Excel&#xff0c;点击 下一步(Next) 3、目前 选择OLE DB Provider &#xff0c;点击 下一步&#xff08;Next&#xff09; 4、默认 &#xff0c;点击 下一步&#xff08;Next&#xff09;…

迅为RK3576开发板Android 多屏显示

迅为iTOP-3576开发板采用瑞芯微RK3576高性能、低功耗的应用处理芯片&#xff0c;集成了4个Cortex-A72和4个Cortex-A53核心&#xff0c;以及独立的NEON协处理器。它适用于ARM PC、边缘计算、个人移动互联网设备及其他多媒体产品。 1.1 Android 多屏同显 iTOP-RK3576 开发板支持…

如何保证光谱相机的稳定性和可靠性

光学系统设计与制造 高质量光学元件&#xff1a;采用高精度研磨和镀膜的透镜、棱镜、光栅等光学元件。优质的透镜可以减少像差和色差&#xff0c;确保光线准确聚焦&#xff1b;高质量的镀膜能够提高光学元件的透光率&#xff0c;降低反射损失&#xff0c;并且增强对不同波段光…

Python GUI Pyside6 实例笔记

例【1】 好的&#xff01;我们将通过一个简单的案例来学习如何使用 PySide6 创建一个基本的桌面应用程序。这个案例将展示如何创建一个带有按钮的窗口&#xff0c;当点击按钮时&#xff0c;会弹出一个消息框。 1. 安装 PySide6 首先&#xff0c;确保你已经安装了 PySide6。如…

CIA-Access V2.5_9_2_10G EPON技术原理_关键技术

10G EPON关键技术&#xff0c;主要包含测距&#xff0c;突发光电技术&#xff0c;DBA以及线路加密。 关键技术之MPCP测距 第一个仍然是测距&#xff0c;每一个ONU到OLT的逻辑距离是不相等的&#xff0c;另外OLT与ONU之间的环路时间也会随着时间和环境的变化而变化&#xff0c;…

PDF文件提取开源工具调研总结

概述 PDF是一种日常工作中广泛使用的跨平台文档格式&#xff0c;常常包含丰富的内容&#xff1a;包括文本、图表、表格、公式、图像。在现代信息处理工作流中发挥了重要的作用&#xff0c;尤其是RAG项目中&#xff0c;通过将非结构化数据转化为结构化和可访问的信息&#xff0…

计算机网络 (43)万维网WWW

前言 万维网&#xff08;World Wide Web&#xff0c;WWW&#xff09;是Internet上集文本、声音、动画、视频等多种媒体信息于一身的信息服务系统。 一、基本概念与组成 定义&#xff1a;万维网是一个分布式、联机式的信息存储空间&#xff0c;通过超文本链接的方式将分散的信息…

ubuntu18.04开发环境下samba服务器的搭建

嵌入式linux的发展很快&#xff0c;最近准备在一个新项目上采用新一代的linux核心板&#xff0c;发现linux内核的版本已经更新到5.4以上甚至6.0以上&#xff1b;之前常用的linux内核版本是2.6.4&#xff0c;虽然在某些项目上还能用但是明显跟不上时代的步伐了&#xff0c;所以要…