欢迎光临
我们一直在努力

【MyBatis-Plus 进阶】注解配置、条件构造器与自定义 SQL的复杂操作详解

文章目录

    • 一、MyBatis-Plus介绍
    • 二、MyBatis-Plus 入门使用
      • 2.1 依赖引入与配置
      • 2.2 入门使用
    • 三、MyBatis-Plus复杂操作
      • 3.1 注解配置
        • 3.1.1 @TableName
        • 3.1.2 @TableField
        • 3.1.3 @TableId
      • 3.2 打印日志
      • 3.3 条件构造器
        • 3.3.1 QueryWrapper
        • 3.3.2 UpdateWrapper
        • 3.3.3 LambdaQueryWrapper
        • 3.3.4 LambdaUpdateWrapper
      • 3.4 自定义SQL

在这里插入图片描述

一、MyBatis-Plus介绍

MyBatis-Plus(简称 MP) 是一个 MyBatis 的增强工具, 在 MyBatis 的基础上只做增强不做改变, 为简化开发、提高效率而生。

特性

  • 润物无声: 只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。
  • 效率至上: 只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间。
  • 丰富功能: 代码生成、自动分页、逻辑删除、自动填充、拦截器等功能一应俱全。
  • 广泛认可: 连续 5 年获得开源中国年度最佳开源项目殊荣,Github 累计 16K Star。

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

官网地址:Mybatis-Plus 简化开发

二、MyBatis-Plus 入门使用

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

2.1 依赖引入与配置

  • 创建springboot工程
  • 添加MyBatis-Plus和MySQL依赖, 配置数据库连接信息
  • Spring Boot2依赖:

    <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.7</version>
    </dependency>

    Spring Boot3依赖:

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

    MySQL依赖:

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

    配置数据库(application.yml文件):

    # 数据库连接配置
    spring:
    datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

    配置数据库(application.properties文件):

    #驱动类名称
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    #数据库连接的url
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    #连接数据库的用户名
    spring.datasource.username=root
    #连接数据库的密码
    spring.datasource.password=root

    2.2 入门使用

  • 创建实体类,实体类的属性名与表中的字段名一一对应:

  • 编写Mapper接口类

  • MybatisPlus提供了一个基础的BaseMapper 接口,已经实现了单表的CRUD,自定义的 Mapper只需要继承这个BaseMapper,就无需自己实现单表CRUD了。

    BaseMapper包含了很多方法,示例:

    在这里插入图片描述

    Mapper接口代码:

    @Mapper
    public interface UserInfoMapper extends BaseMapper<UserInfo> {
    }

    也可以在启动类上添加 @MapperScan ,扫描Mapper文件夹,如下:(二选一即可) 在这里插入图片描述

  • CRUD单元测试
  • 在创建出来的SpringBoot工程中,在src下的test目录下,创建测试类,可以直接使用这个测试类来进行测试。

    编写单元测试,测试基本的CRUD功能:

    @SpringBootTest
    class MybatisPlusDemoApplicationTests {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    public void testSelect() {
    System.out.println(("—– selectAll method test ——"));
    List<UserInfo> userList = userInfoMapper.selectList(null);
    userList.forEach(System.out::println);
    }
    }

    运行结果如下:

    在这里插入图片描述

    三、MyBatis-Plus复杂操作

    3.1 注解配置

    MyBatis是如何知道,我们要操作的是哪张表,表里有哪些字段呢?

    @Mapper
    public interface UserInfoMapper extends BaseMapper<UserInfo> {
    }

    UserInfoMapper 在继承BaseMapper 时, 指定了一个泛型, 这个UserInfo就是与数据库表相对应的实体类。MyBatis-Plus会根据这个实体类来推断表的信息。

    默认情况下:

  • 表名: 实体类的驼峰表示法转换成蛇形表示法(下划线分割), 作为表名。比如UserInfo -> user_info
  • 字段: 根据实体类的属性名转换为蛇形表示法作为字段名。比如deleteFlag -> delete_flag
  • 主键: 默认为id
  • 如果实体类和数据库不是按照上述规则定义。MyBatis-Plus也给我们提供了一些注解,用来标识表的信息。

    3.1.1 @TableName

    该注解用于指定实体类对应的数据库表名。当实体类名与数据库表名不一致,或者实体类名不是数据库表名的驼峰写法时,可以使用这个注解来明确指定表名。

    示例:

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

    3.1.2 @TableField

    该注解用于标记实体类中的非主键字段,它告诉 MyBatis-Plus 如何映射实体类字段到数据库表字段。如果实体类字段名遵循驼峰命名规则,并且与数据库表字段名一致,可以省略这个注解。

    示例:

    @Data
    @TableName("user_info")
    public class Userinfo {
    private 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;
    }

    3.1.3 @TableId

    该注解用于标记实体类中的主键字段。如果你的主键字段名为 id,可以省略这个注解。

    示例:

    @Data
    @TableName("user_info")
    public class Userinfo {
    @TableId("id")
    private Integer userId;
    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 注解就可以。

    @TableId 参数介绍:

  • value 类型:String 默认值:"" 描述:指定数据库表的主键字段名。如果不设置,MyBatis-Plus 将使用实体类中的字段名作为数据库表的主键字段名。

  • type 类型:Enum 默认值:IdType.NONE 描述:指定主键的生成策略。

  • IdType 枚举类型定义

    • IdType.AUTO:使用数据库自增 ID 作为主键。
    • IdType.NONE:无特定生成策略,如果全局配置中有 IdType 相关的配置,则会跟随全局配置。
    • IdType.INPUT:在插入数据前,由用户自行设置主键值。
    • IdType.ASSIGN_ID:自动分配 ID,适用于 Long、Integer、String 类型的主键。默认使用雪花算法通过 IdentifierGenerator 的 nextId 实现。
    • IdType.ASSIGN_UUID:自动分配 UUID,适用于 String 类型的主键。默认实现为 IdentifierGenerator 的 nextUUID 方法。

    详情参考网址:注解配置


    3.2 打印日志

    Mybatis-Plus配置日志如下(application.yml):

    mybatis-plus:
    configuration: # 配置打印 MyBatis日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    3.3 条件构造器

    MyBatis-Plus 提供了一套强大的条件构造器(Wrapper), 用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件, 无需编写繁琐的 SQL 语句, 从而提高开发效率并减少 SQL 注入的风险。

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

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

    QueryWrapper并不只用于查询语句, 无论是修改, 删除, 查询, 都可以使用QueryWrapper来构建查询条件。

  • 查询
  • 完成SQL:

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

    测试代码:

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

  • 更新
  • 完成SQL:

    UPDATE user_info SET delete_flag=? WHERE age < 20

    测试代码:

    @Test
    @Test
    void testUpdateByQueryWrapper(){
    QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
    queryWrapper.lt("age",20);
    UserInfo userInfo = new UserInfo();
    userInfo.setDeleteFlag(1);
    userInfoMapper.update(userInfo,queryWrapper);
    }

    条件方法说明:

    • 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

    测试代码:

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

    }

    3.3.2 UpdateWrapper

    对于更新,也可以直接使用 UpdateWrapper,在不创建实体对象的情况下,直接设置更新字段和条件。

  • 基础更新
  • 完成SQL:

    UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)

    测试代码:

    @Test
    void testUpdateWrapper(){
    UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();

    updateWrapper.set("delete_flag",1).set("age",5).in("id",List.of(2,3,5,8));
    userInfoMapper.update(updateWrapper);
    }

  • 基于SQL更新
  • 完成SQL:

    UPDATE user_info SET age = age+10 WHERE id IN (1,2,3)

    测试代码:

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

    3.3.3 LambdaQueryWrapper

    QueryWrapper 和 UpdateWrapper存在一个问题, 就是需要写死字段名, 如果字段名发生变更, 可能会因为测试不到位酿成事故。

    MyBatis-Plus 提供了一种基于Lambda表达式的条件构造器, 它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名,也提高了代码的可读性和可维护性。

    • LambdaQueryWrapper
    • LambdaUpdateWrapper

    分别对应上述的QueryWrapper和UpdateWrapper。

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

    3.3.4 LambdaUpdateWrapper

    LambdaUpdateWrapper用法和 LambdaQueryWrapper相似:

    @Test
    void testLambdaUpdateByUpdateWrapper(){
    UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();
    updateWrapper.lambda()
    .set(UserInfo::getDeleteFlag, 0)
    .set(UserInfo::getAge, 5)
    .in(UserInfo::getId, List.of(1,2,3));
    userInfoMapper.update(null, updateWrapper);
    }

    3.4 自定义SQL

    在实际的开发中, MyBatis-Plus提供的操作不能满足所有的实际需求, MyBatis-Plus 也提供了自定义 SQL的功能, 可以利用Wrapper构造查询条件, 再结合Mapper编写SQL。

    • 注:为了使用这一功能, mybatis-plus 版本不低于 3.0.7。

    代码示例1 完成下述SQL查询:

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

    Mapper:

    @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);
    }

    测试代码:

    @Test
    void testQueryUserByCustom(){
    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 语句。

    代码示例2

    MyBatis-Plus 在 MyBatis 的基础上只做增强不做改变, 所以也支持XML的实现方式。上述功能也可以使用XML的方式完成。

    配置mapper路径(application.yml):

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

    Mapper:

    List<UserInfo> queryUserByCustom2(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);

    编写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.bite.mybatis.plus.mapper.UserInfoMapper">

    <select id="queryUserByCustom2" resultType="com.bite.mybatis.plus.entity.UserInfo">
    select id,username,password,age FROM user_info ${ew.customSqlSegment}
    </select>

    </mapper>

    测试:

    @Test
    void testQueryUserByCustom2(){
    QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
    .eq("username","admin");

    userInfoMapper.queryUserByCustom2(queryWrapper).forEach(System.out::println);
    }

    赞(0)
    未经允许不得转载:171主机测评 » 【MyBatis-Plus 进阶】注解配置、条件构造器与自定义 SQL的复杂操作详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址