MyBatis-Plus学习与使用

这是我的gitee地址,可以在上面拉代码下来看,对照看比较容易理解

https://gitee.com/workRep/spring-cloud-learn.git

1、MyBatis-plus快速入门使用

MyBatis-Plus的官方网站,上面有很详细的各种文档,后续需要可以去查询

简介 | MyBatis-Plushttps://baomidou.com/introduce/首先我们需要知道一点,Mybatisplus是可以完美兼容MyBatis的,也就是说,如果你之前用的是MyBatis的话,可以无感切换成Mybatisplus的

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

这是他官网上的一句话,用来定义和描述Mybatisplus的

如果之前是Mybatis的项目的话,直接把依赖替换成Mybatisplus的就可以了,照常可以使用的

<!--        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.15</version>
        </dependency>
 <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.25</version>
        </dependency>

导入之后记得刷新依赖

如果是直接使用Mybatisplus的话,新建了Springboot项目之后,除了依赖的添加,还需要添加配置文件

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: root
    password: 密码
    driver-class-name: com.mysql.cj.jdbc.Driver

SQL

CREATE TABLE `user` (
  `id` bigint NOT NULL,
  `name` varchar(30) DEFAULT NULL,
  `pwd` varchar(30) DEFAULT NULL,
  `create_by` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_by` varchar(255) DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `del_flag` varchar(1) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT '0',
  `remark` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3

这边新建一个BaseEntity

package com.jha.springcloudlearn.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;
@Data
public class BaseEntity implements Serializable {
    //创建人,插入时自动填充
    //@TableField(fill = FieldFill.INSERT)
    private String createBy;
    //更新人,插入时自动填充
    //@TableField(fill = FieldFill.INSERT_UPDATE)
    private String updateBy;
    //创建时间,插入时自动填充
    @TableField(fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    //更新时间,插入时自动填充
    @TableField(fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date updateTime;
    //逻辑删除字段
    @TableLogic
    private String delFlag;
    /**
     * 备注
     */
    @TableField(exist = false)
    private String remark;
}

新建一个User实体类

package com.jha.springcloudlearn.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName(
        value = "user",           // 指定表名为 user
        schema = "mybatis",              // 指定数据库 Schema 为 mybatis
        keepGlobalPrefix = true,           // 保持使用全局表前缀
        resultMap = "userResultMap",       // 指定 XML 中的 resultMap ID
        autoResultMap = true,              // 自动构建 resultMap
        excludeProperty = {"pwd", "salt"} // 排除 password 和 salt 属性
)
//@TableName("user")
public class User extends BaseEntity {
    //@TableId(value = "id",type = IdType.AUTO)//自增
    @TableId(value = "id", type = IdType.ASSIGN_ID)//雪花
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
    @TableField(value = "name")
    private String name;
    private String pwd;

    private String salt;
    private String phone;

}

新建vo、bo

UserVo

package com.jha.springcloudlearn.entity.vo;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.jha.springcloudlearn.entity.BaseEntity;
import lombok.Data;

@Data
public class UserVo extends BaseEntity {
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id;
    private String name;
    private String pwd;
}

UserBo

package com.jha.springcloudlearn.entity.bo;

import com.jha.springcloudlearn.entity.User;

public class UserBo extends User {
}

然后我们需要实现自动填充功能的话,需要实现MetaObjectHandler接口

添加一个MyMetaObjectHandler

package com.jha.springcloudlearn.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jha.springcloudlearn.entity.BaseEntity;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        try {
            if (metaObject != null && metaObject.getOriginalObject() instanceof BaseEntity) {
                BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
                Date current =  (baseEntity.getCreateTime())!= null
                        ? baseEntity.getCreateTime() : new Date();
                baseEntity.setCreateTime(current);
                baseEntity.setUpdateTime(current);
            }
        } catch (Exception e) {
            throw new RuntimeException("自动注入异常 => " + e.getMessage());
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        if (metaObject != null && metaObject.getOriginalObject() instanceof BaseEntity) {
            BaseEntity baseEntity = (BaseEntity) metaObject.getOriginalObject();
            Date current =  (baseEntity.getUpdateTime())!= null
                    ? baseEntity.getUpdateTime() : new Date();
            baseEntity.setUpdateTime(current);
        }
        // 更新时自动填充更新时间
       // this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());

        // 如果需要,可以设置更新人
        // this.strictUpdateFill(metaObject, "updateBy", String.class, "system");
    }
}

这样就可以完成创建时间,更新时间的自动填充了,至于创建人和修改人,这个需要用到token,暂且不实现。

我们添加测试的控制层-服务层-mapper层

controller

package com.jha.springcloudlearn.controller;

import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserInfoController {
    @Autowired
    private IUserService iUserService;
    @GetMapping("/info")
    public List<User> info() {
        return iUserService.ListUsers();
    }
    @DeleteMapping("/delete/{id}")
    public Boolean delete(@PathVariable String id) {
        return iUserService.deleteUser(id);
    }
    @PostMapping("/add")
    public Boolean add(@RequestBody User user) {
        return iUserService.addUser(user);
    }
}

Service

package com.jha.springcloudlearn.service;

import com.jha.springcloudlearn.entity.User;

import java.util.List;

public interface IUserService {
    public abstract List<User> ListUsers();
    public abstract Boolean addUser(User  user);
    public abstract Boolean deleteUser(String  id );
}

ServiceImp

package com.jha.springcloudlearn.service.impl;

import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.mapper.UserMapper;
import com.jha.springcloudlearn.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
public class UserServiceImp implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public List<User> ListUsers() {
        return userMapper.SelectUsers();
    }

    @Override
    public Boolean addUser(User user) {
        return userMapper.insert(user) > 0;
    }

    @Override
    public Boolean deleteUser(String id) {
        return userMapper.deleteById(id) > 0;
    }
}

Mapper

package com.jha.springcloudlearn.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jha.springcloudlearn.entity.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
@Mapper
public interface UserMapper extends BaseMapper<User> {
    public List<User> SelectUsers();
}

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.jha.springcloudlearn.mapper.UserMapper">
    <resultMap id="userResultMap" type="com.jha.springcloudlearn.entity.User">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="pwd" property="pwd"/>
        <result column="create_by" property="createBy"/>
        <result column="update_by" property="updateBy"/>
        <result column="create_time" property="createTime"/>
        <result column="update_time" property="updateTime"/>
        <result column="del_flag" property="delFlag"/>
    </resultMap>
    <select id="SelectUsers" resultMap="userResultMap">
        SELECT * FROM user;
    </select>
</mapper>

运行测试,新增用户,删除用户就能发现可以看到创建时间个更新时间自动填充上去了

常用注解

@TableName

用来指定表名,指定实体类对应的数据库表名。当实体类名与数据库表名不一致,或者实体类名不是数据库表名的驼峰写法时,需要使用这个注解来明确指定表名。一般来说按照驼峰来命名的不存在这个问题

value

类型: String
默认值: ""

指定实体类对应的数据库表名。如果实体类名与表名不一致,使用这个属性来指定正确的表名。

一般如果只有value使用的话,不用显式的声明

如:@TableName("user")

schema

类型: String
默认值: ""

指定数据库的 Schema 名称。通常情况下,如果你的数据库没有使用 Schema 来组织表,这个属性可以不填写。

keepGlobalPrefix

类型: boolean
默认值: false

当全局配置了 tablePrefix 时,这个属性决定是否保持使用全局的表前缀。如果设置为 true,即使注解中指定了表名,也会自动加上全局的表前缀。一般不使用

resultMap

类型: String
默认值: ""

指定在 XML 中定义的 ResultMap 的 ID,用于将查询结果映射到特定类型的实体类对象。

autoResultMap

类型: boolean
默认值: false

是否自动构建 resultMap。如果已经设置了 resultMap,这个属性不会生效。

excludeProperty

类型: String[]
默认值: {}

指定在映射时需要排除的属性名。这些属性将不会被包含在生成的 SQL 语句中。

一般来说大部分时间只用到value属性

@TableId

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

value

类型: String
默认值: ""

指定数据库表的主键字段名。如果不设置,MyBatis-Plus 将使用实体类中的字段名作为数据库表的主键字段名。

type

类型: Enum
默认值: IdType.NONE

指定主键的生成策略。

IdType 枚举类型定义

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

一般用雪花id,比较安全

@TableField

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

value

类型: String
默认值: ""

指定数据库中的字段名。如果你的实体类字段名与数据库字段名不同,使用这个属性来指定正确的数据库字段名。

exist

类型: boolean
默认值: true

指示这个字段是否存在于数据库表中。如果设置为 false,MyBatis-Plus 在生成 SQL 时会忽略这个字段。

condition

类型: String
默认值: ""

在执行实体查询(EntityQuery)时,指定字段的条件表达式。这允许你自定义字段在 WHERE 子句中的比较方式。如果该项有值则按设置的值为准,无值则默认为全局的 %s=#{%s} 为准。

fill

类型: Enum
默认值: FieldFill.DEFAULT

字段自动填充策略。该属性用于指定在执行数据库操作(如插入、更新)时,如何自动填充字段的值。通过使用 FieldFill 枚举,可以灵活地控制字段的填充行为。

FieldFill枚举类型定义

  • FieldFill.DEFAULT:默认不进行填充,依赖于数据库的默认值或手动设置。

  • FieldFill.INSERT:在插入操作时自动填充字段值。

  • FieldFill.UPDATE:在更新操作时自动填充字段值。

  • FieldFill.INSERT_UPDATE:在插入和更新操作时都会自动填充字段值。

一般用在字段填充

@TableLogic

该注解用于标记实体类中的字段作为逻辑删除字段。逻辑删除是一种数据管理策略,它不是真正地从数据库中删除记录,而是在记录中标记该记录为已删除状态。通过使用@TableLogic注解,MyBatis-Plus 可以在查询、更新和删除操作中自动处理逻辑删除字段的值。

@TableLogic(value = "0", delval = "1") // 逻辑删除字段

deleted字段被标记为逻辑删除字段。@TableLogic注解的value属性指定了逻辑未删除的值(在这个例子中是0),而delval属性指定了逻辑删除的值(在这个例子中是1)

当执行查询操作时,MyBatis-Plus 会自动过滤掉标记为逻辑删除的记录,只返回未删除的记录。在执行更新操作时,如果更新操作会导致逻辑删除字段的值变为逻辑删除值,MyBatis-Plus 会自动将该记录标记为已删除。在执行删除操作时,MyBatis-Plus 会自动将逻辑删除字段的值更新为逻辑删除值,而不是物理删除记录。

使用@TableLogic注解可以实现数据的逻辑删除,有助于维护数据的完整性和可追溯性,同时避免了物理删除操作可能带来的数据丢失风险。开发者无需手动编写逻辑删除的代码,MyBatis-Plus 会自动处理这一过程。

常用配置

mybatis-plus:
  # 配置mybatis-plus的mapper.xml文件位置,默认值:classpath*:/mapper/**/*.xml
  mapper-locations: classpath*:/mapper/**/*.xml
  # 配置mybatis-plus的entity别名,配置之后,就可以在mapper.xml中使用别名,而不需要使用全类名,不需要再写全路径名
  type-aliases-package: com.example.demo.entity
  # 配置mybatis-plus的配置文件
  global-config:
    # 数据库配置
    db-config:
      #id雪花生成
      id-type: assign_id
      #逻辑删除字段
      logic-delete-field: del_flag
      #字段策略,  not_empty: 不是空就更新,  always: 永远更新,  never: 默认,  ignored: 忽略,  not_null: 不是null就更新
      update-strategy: not_null
      #逻辑删除字段值
      logic-delete-value: 2
      #逻辑未删除字段值
      logic-not-delete-value: 0
  # 配置mybatis-plus的日志
  configuration:
    # 打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #是否开启下划线和驼峰映射
    map-underscore-to-camel-case: true
    #懒加载
    lazy-loading-enabled: true
    #是否开启二级缓存
    cache-enabled: false

这边是Mybatisplus的全局配置,如果实体类没有注解的话,就按照这个去执行,如果有,就按照实体类上的注解去执行,注解优先级>全局配置

很多都是默认的配置,按照需要去找对应的配置即可

条件构造器

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

在 MyBatis-Plus 中,Wrapper 类是构建查询和更新条件的核心工具。以下是主要的 Wrapper 类及其功能:

  • AbstractWrapper:这是一个抽象基类,提供了所有 Wrapper 类共有的方法和属性。它定义了条件构造的基本逻辑,包括字段(column)、值(value)、操作符(condition)等。所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。

  • QueryWrapper:专门用于构造查询条件,支持基本的等于、不等于、大于、小于等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用 and 和 or 逻辑。

  • UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。

  • LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下。

  • LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。

package com.jha.springcloudlearn;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.jha.springcloudlearn.entity.BaseEntity;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.mapper.UserMapper;
import com.jha.springcloudlearn.service.impl.UserServiceImp;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Date;
import java.util.List;

@SpringBootTest
class SpringCloudLearnApplicationTests {
    @Autowired
    private UserMapper userMapper;

    @Test
    void contextLoads() {
    }

    //基于QueryWrapper的查询
    @Test
    void testSelectByQueryWrapper() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        //查询条件添加,查询创建时间在2025-12-08 03:19:17之后的用户,并且名字包含a,查询字段为id,name,pwd
        userQueryWrapper.select("id","name","pwd").like("name","a").ge("create_time","2025-12-08 03:19:17");
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println( users);
    }

    //基于LambdaQueryWrapper的查询
    @Test
    void testSelectByLambdaQueryWrapper() {
        LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
        //查询条件添加,查询创建时间在2025-12-08 03:19:17之后的用户,并且名字包含a,查询字段为id,name,pwd
        userQueryWrapper.select(User::getId,User::getName,User::getPwd).like(User::getName,"a").ge(BaseEntity::getCreateTime,"2025-12-08 03:19:17");
        List<User> users = userMapper.selectList(userQueryWrapper);
        System.out.println( users);
    }
    //基于QueryWrapper的修改
    @Test
    void testUpdateByQueryWrapper() {
        User user = new User();
        user.setPwd("231");  // 只设置需要更新的字段
        user.setRemark("批量修改");
        QueryWrapper<User> updateWrapper = new QueryWrapper<User>();
        QueryWrapper<User> eq = updateWrapper.like("name", "jh");
        int update = userMapper.update(user, eq);
    }

    //基于LambdaQueryWrapper的修改
    @Test
    void testUpdateByLambdaQueryWrapper() {
        User user = new User();
        user.setPwd("233211");  // 只设置需要更新的字段
        user.setRemark("批量修改");
        LambdaQueryWrapper<User> updateWrapper = new LambdaQueryWrapper<User>();
        LambdaQueryWrapper<User> eq = updateWrapper.like(User::getName, "jh");
        int update = userMapper.update(user, eq);
    }
    @Test
    void testDeleteByQueryWrapper() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "测试");
        int delete = userMapper.delete(queryWrapper);
    }

    //基于UpdateWrapper的修改
    @Test
    void testUpdateByUpdateWrapper() {
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<User>();
        //设置密码为密码+10000,remark为220871,名字包含jh
        UpdateWrapper<User> set = updateWrapper.like("name", "jh").set("remark", "220871")
                .setSql("pwd=pwd+10000");
        int update = userMapper.update(null, set);
    }

}

QueryWrapper和LambdaQueryWrapper的主要区别在于,一个是硬编码,一个不是

常用的几个方法:

allEq(全等于)

allEq 方法是 MyBatis-Plus 中用于构建查询条件的方法之一,它允许我们通过一个 Map 来设置多个字段的相等条件。

方法签名

allEq(Map<String, Object> params)
allEq(Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, Map<String, Object> params, boolean null2IsNull)

// 设置所有字段的相等条件,通过filter过滤器决定哪些字段应该被包含,如果字段值为null,则根据null2IsNull参数决定是否设置为IS NULL
allEq(BiPredicate<String, Object> filter, Map<String, Object> params)
allEq(BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<String, Object> filter, Map<String, Object> params, boolean null2IsNull)

参数说明

  • params:一个 Map,其中 key 是数据库字段名,value 是对应的字段值。
  • null2IsNull:如果设置为 true,当 Map 中的 value 为 null 时,会调用 isNull 方法;如果设置为 false,则会忽略 value 为 null 的键值对。
  • filter:一个 BiPredicate,用于过滤哪些字段应该被包含在查询条件中。
  • condition:一个布尔值,用于控制是否应用这些条件。
//基于QueryWrapper的查询,allEq
    @Test
    void testAllEq() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        Map<String, Object> params = new HashMap<>();
        params.put("id", "1997868875736465410");
        params.put("name", "w2uhu");
        params.put("pwd", "220871");
        queryWrapper.allEq(params);
        // 查询所有字段,全条件匹配
        List<User> users = userMapper.selectList(null, queryWrapper);
        System.out.println(users);
        System.out.println("======================");
        QueryWrapper<User> queryWrapper2 = new QueryWrapper<User>();
        // 查询条件添加,键包含a才用作条件
        queryWrapper2.allEq((field, value) -> field.contains("a"),params);
        List<User> users2 = userMapper.selectList(null, queryWrapper2);
    }

可以过滤器来动态设置条件

eq(单等于)

eq 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的相等条件。

使用范围

  • QueryWrapper
  • LambdaQueryWrapper
  • UpdateWrapper
  • LambdaUpdateWrapper

方法签名

// 设置指定字段的相等条件
eq(R column, Object val)

// 根据条件设置指定字段的相等条件
eq(boolean condition, R column, Object val)

参数说明

  • column:数据库字段名或使用 Lambda 表达式的字段名。
  • val:与字段名对应的值。
  • condition:一个布尔值,用于控制是否应用这个相等条件。

ne(不相等)

ne 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的不相等条件。

使用范围

  • QueryWrapper
  • LambdaQueryWrapper
  • UpdateWrapper
  • LambdaUpdateWrapper

方法签名

// 设置指定字段的不相等条件
ne(R column, Object val)

// 根据条件设置指定字段的不相等条件
ne(boolean condition, R column, Object val)

参数说明

  • column:数据库字段名或使用 Lambda 表达式的字段名。
  • val:与字段名对应的值。
  • condition:一个布尔值,用于控制是否应用这个不相等条件。

gt(大于)

gt 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的大于条件。

使用范围

  • QueryWrapper
  • LambdaQueryWrapper
  • UpdateWrapper
  • LambdaUpdateWrapper

方法签名

// 设置指定字段的大于条件
gt(R column, Object val)

// 根据条件设置指定字段的大于条件
gt(boolean condition, R column, Object val)

参数说明

  • column:数据库字段名或使用 Lambda 表达式的字段名。
  • val:与字段名对应的值。
  • condition:一个布尔值,用于控制是否应用这个大于条件。

ge(大于等于)

ge 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的大于等于条件。

使用范围

  • QueryWrapper
  • LambdaQueryWrapper
  • UpdateWrapper
  • LambdaUpdateWrapper

方法签名

// 设置指定字段的大于等于条件
ge(R column, Object val)

// 根据条件设置指定字段的大于等于条件
ge(boolean condition, R column, Object val)

参数说明

  • column:数据库字段名或使用 Lambda 表达式的字段名。
  • val:与字段名对应的值。
  • condition:一个布尔值,用于控制是否应用这个大于等于条件。

lt(小于)

lt 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的小于条件。

使用范围

  • QueryWrapper
  • LambdaQueryWrapper
  • UpdateWrapper
  • LambdaUpdateWrapper

方法签名

// 设置指定字段的小于条件
lt(R column, Object val)

// 根据条件设置指定字段的小于条件
lt(boolean condition, R column, Object val)

参数说明

  • column:数据库字段名或使用 Lambda 表达式的字段名。
  • val:与字段名对应的值。
  • condition:一个布尔值,用于控制是否应用这个小于是条件。

le(小于等于)

le 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的小于等于条件。

使用范围

  • QueryWrapper
  • LambdaQueryWrapper
  • UpdateWrapper
  • LambdaUpdateWrapper

方法签名

// 设置指定字段的小于等于条件
le(R column, Object val)

// 根据条件设置指定字段的小于等于条件
le(boolean condition, R column, Object val)

参数说明

  • column:数据库字段名或使用 Lambda 表达式的字段名。
  • val:与字段名对应的值。
  • condition:一个布尔值,用于控制是否应用这个小于是条件。

between

between 方法是 MyBatis-Plus 中用于构建查询条件的基本方法之一,它用于设置单个字段的 BETWEEN 条件。

使用范围

  • QueryWrapper
  • LambdaQueryWrapper
  • UpdateWrapper
  • LambdaUpdateWrapper

方法签名

// 设置指定字段的 BETWEEN 条件
between(R column, Object val1, Object val2)

// 根据条件设置指定字段的 BETWEEN 条件
between(boolean condition, R column, Object val1, Object val2)

参数说明

  • column:数据库字段名或使用 Lambda 表达式的字段名。
  • val1:与字段名对应的第一个值,表示 BETWEEN 条件的起始值。
  • val2:与字段名对应的第二个值,表示 BETWEEN 条件的结束值。
  • condition:一个布尔值,用于控制是否应用这个 BETWEEN 条件。

自定义SQL

可以利用Mybatisplus的Wrapper来构建复杂的where条件,然后自己定义SQL语句中剩下的部分

添加mapper,用于处理自定义SQL

/**
     * 自定义SQL
     * @param queryWrapper, 必须使用@Param("ew"),必须命名为ew
     * @param count
     * @return
     *
     */
    Integer updateBySQL(@Param("ew") QueryWrapper<User> queryWrapper,@Param("count") Integer count)

mapper.xml中添加

    <update id="updateBySQL">
        UPDATE user SET pwd = pwd+#{count} ${ew.customSqlSegment};
    </update>

测试方法

@Test
    void testSQL(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
        List<String> ids = new ArrayList<>();
        ids.add("1997868875736465410");
        ids.add("1997875395392012290");
        queryWrapper.in("id", ids);
        Integer count=100000;
        //把where条件在QueryWrapper中写好,然后传给updateBySQL方法(自定义SQL方法,在里面写select查询,除去where条件)
        Integer num= userMapper.updateBySQL(queryWrapper,count);
        System.out.println("更新数量:"+num);
    }

持久层接口(IService)

IService接口是 MyBatis-Plus 提供的一个通用 Service 层接口,它封装了常见的 CRUD 操作,包括插入、删除、查询和分页等。通过继承 IService 接口,可以快速实现对数据库的基本操作,同时保持代码的简洁性和可维护性。

IService 接口中的方法命名遵循了一定的规范,如 get 用于查询单行,remove 用于删除,list 用于查询集合,page 用于分页查询,这样可以避免与 Mapper 层的方法混淆。

想要使用的话,我们的接口需要去继承IService接口,实现类如果直接实现我们的自定义接口的话,就会存在一个问题,我们需要实现所有的接口,而IService有非常多的接口,这是不现实的,于是Mybatisplus为我们提供了一个IService的实现类,ServiceImp,这个接口就实现了IService接口的方法,我们只需要在我们的实现类实现我们的接口的同时去继承ServiceImp就可以得到IService的所有方法了。

使用示例

新增MyUserMapper.java

package com.jha.springcloudlearn.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jha.springcloudlearn.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface MyUserMapper extends BaseMapper<User> {
}

新增IMyUserService

package com.jha.springcloudlearn.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.jha.springcloudlearn.entity.User;

public interface IMyUserService  extends IService<User> {
}

新增MyUserServiceImp

package com.jha.springcloudlearn.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.mapper.MyUserMapper;
import com.jha.springcloudlearn.service.IMyUserService;
import org.springframework.stereotype.Service;

@Service
public class MyUserServiceImp extends ServiceImpl<MyUserMapper, User> implements IMyUserService {
}

添加测试类测试

package com.jha.springcloudlearn.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jha.springcloudlearn.entity.User;
import com.jha.springcloudlearn.service.IMyUserService;
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 MyUserServiceImpTest {
    @Autowired
    private IMyUserService myUserService;
    //测试IService的方法
    @Test
    void selectByQueryWrapper() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name","测试");
        User one = myUserService.getOne(queryWrapper);
        System.out.println(one);
    }
    @Test
    void selectByLambdaQueryWrapper() {
        List<User> list = myUserService.list();
        for (User user : list) {
            System.out.println( user);
        }
    }
    @Test
    void testAdd() {
        User user = new User();
        user.setName("测试");
        user.setPwd("123456");
        boolean save = myUserService.save(user);
        System.out.println(save);
    }

}

IService中的lambdaQuery和lambdaUpdate方法

用于条件查询,当某个条件不成立的时候,不添加对应的条件

 @Test
    void testLambdaQuery() {
        UserBo userBo = new UserBo();
        userBo.setName("测试");
        userBo.setPwd("123456");
        //userBo.setId(1997855873826029570L);

        //查询条件有:姓名,密码,id
        List<User> list = myUserService.lambdaQuery().like(userBo.getName() != null, User::getName, userBo.getName())
                .eq(userBo.getId() != null, User::getId, userBo.getId())
                .eq(userBo.getPwd() != null, User::getPwd, userBo.getPwd())
                .list();

        for (User user : list) {
            System.out.println( user);
        }
    }
    @Test
    void testLambdaUpdate() {
        UserBo userBo = new UserBo();
        userBo.setName("测试");
        userBo.setPwd("123456");
        userBo.setId(1998231604640882689L);
        Long newPwd=Long.parseLong(userBo.getPwd()) -200000L;
        myUserService.lambdaUpdate().eq(User::getId, userBo.getId())
                .set(newPwd >=0,User::getPwd, newPwd)
                .set(newPwd <=0,User::getPwd, "0")
                .set(newPwd <=0, User::getRemark, "密码不够减")
                .update();
    }
url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true

配置文件中的jdbc连接,改成这个,添加重写批处理语句支持rewriteBatchedStatements=true

DB静态工具

为了编码循环依赖,而设计的,DB中包含了IService中所有的方法,只不过里面是静态的,直接调用即可,调用时需要传入类型

示例测试

 @Test
    void testSelectByQueryWrapper() {
        // 查询单个用户
        User user = Db.lambdaQuery(User.class)
                .eq(User::getId, 1998231604640882689L)
                .one();
        System.out.println("单个用户: " + user);
        System.out.println("======================");

        // 查询用户列表
        List<User> list = Db.lambdaQuery(User.class)
                .like(User::getName, "测试")
                .list();
        System.out.println("用户列表: ");
        for (User user1 : list) {
            System.out.println(user1);
        }
    }

枚举处理器

在日常开发中,有很多东西需要使用到枚举,如状态,就拿删除状态来说,使用枚举来进行表示

我们添加枚举类

DelEnums

package com.jha.springcloudlearn.entity.enums;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;

@Getter
public enum DelEnums {
    Nomal(0,"正常"),
    Del(2,"删除");
    //枚举值
    @EnumValue   //数据库保存的枚举值
    private Integer value;
    @JsonValue    //枚举对应返回什么就加上这个注解
    private String desc;

    DelEnums(Integer value, String desc) {
        this.value = value;
        this.desc = desc;
    }
}

然后配置文件添加

server:
  port: 8081

#mybatis:
#  # 指定别名设置的包为所有entity
#  type-aliases-package: com.jha.springcloudlearn.entity
#  configuration:
#    map-underscore-to-camel-case: true # 驼峰命名规范
#  mapper-locations: classpath:/mapper/*.xml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
    username: root
    password: 220717
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
  # 配置mybatis-plus的mapper.xml文件位置,默认值:classpath*:/mapper/**/*.xml
  mapper-locations: classpath*:/mapper/**/*.xml
  # 配置mybatis-plus的entity别名,配置之后,就可以在mapper.xml中使用别名,而不需要使用全类名,不需要再写全路径名
  type-aliases-package: com.example.demo.entity
  # 配置mybatis-plus的配置文件
  global-config:
    # 数据库配置
    db-config:
      #id雪花生成
      id-type: assign_id
      #逻辑删除字段
      logic-delete-field: del_flag
      #字段策略,  not_empty: 不是空就更新,  always: 永远更新,  never: 默认,  ignored: 忽略,  not_null: 不是null就更新
      #update-strategy: not_null
      #逻辑删除字段名
      logic-delete-feild-name: del_flag
      #逻辑删除字段值
      logic-delete-value: 2
      #逻辑未删除字段值
      logic-not-delete-value: 0
  # 配置mybatis-plus的日志
  configuration:
    # 打印sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    #是否开启下划线和驼峰映射
    map-underscore-to-camel-case: true
    #懒加载
    lazy-loading-enabled: true
    #是否开启二级缓存
    cache-enabled: false
    #枚举类型处理器
    default-enum-type-handler: org.apache.ibatis.type.EnumTypeHandler
default-enum-type-handler: org.apache.ibatis.type.EnumTypeHandler

就是表示添加枚举处理器

分页处理

Mybatisplus本身带有分页插件,只需要手动添加一下就可以了,创建一个MybatisPlusConfig类

在新建之前,我们需要知道我们的Mybatisplus的版本是不是在v3.5.9 之上,因为从这个版本开始,PaginationInnerInterceptor 就被分离出去了,需要额外添加依赖

mybatis-plus-jsqlparser

   <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-jsqlparser</artifactId>
            <version>3.5.12</version>
        </dependency>
package com.jha.springcloudlearn.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(getPaginationInnerInterceptor());
        return interceptor;
    }

    public PaginationInnerInterceptor getPaginationInnerInterceptor() {
        PaginationInnerInterceptor mybatisPlusInterceptor = new PaginationInnerInterceptor();
        //设置数据库类型、 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
        mybatisPlusInterceptor.setDbType(DbType.MYSQL);
        //溢出总页数后是否进行处理,分页合理化
        mybatisPlusInterceptor.setOverflow(true);
        //单页分页条数限制
        mybatisPlusInterceptor.setMaxLimit(1000L);
        return mybatisPlusInterceptor;
    }
}

这样就表示引入了分页插件

然后我们可以在测试类中测试一下

 @Test
    void testPage (){
        Page<User> page=Page.of(1, 3);
        page.addOrder(OrderItem.desc("create_time"));
        Page<User> page1 = myUserService.page(page);
        page1.getRecords().forEach(System.out::println);

    }

这是直接调用page方法来做查询,用来测试分页是否启用了的,实际开发中,一般不这么做

如下示例:

我们需要先封装PageQuery(存在分页的条件,如页码,每页大小,以及创建Page对象的方法等),TableDataInfo(用来返回分页的结果对象的)

PageQuery

package com.jha.springcloudlearn.entity;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;

import java.io.Serializable;
@Data
public class PageQuery implements Serializable {
    private Integer pageNum;
    private Integer pageSize;
    private String sortColumn;
    private String isAsc;
    public <T> Page<T> build(){
        return new Page<>(pageNum,pageSize);
    }
}

TableDataInfo

package com.jha.springcloudlearn.entity;

import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.Data;

import java.util.List;

@Data
public class TableDataInfo<T> {
    private int code;
    private String msg;
    private long total;
    private List<T> rows;

    public static <T> TableDataInfo<T> build(IPage<T> page) {
        TableDataInfo<T> rsp = new TableDataInfo<>();
        rsp.setCode(200);
        rsp.setMsg("查询成功");
        rsp.setRows(page.getRecords());
        rsp.setTotal(page.getTotal());
        return rsp;
    }

}

添加控制层方法

    @GetMapping("/pageList")
    public Page<UserVo> pageList(UserBo userBo, PageQuery pageQuery) {
        return iUserService.pageList(userBo, pageQuery);
    }

IUserService

    public abstract Page<UserVo> pageList(UserBo user, PageQuery  query);

UserServiceImp

    @Override
    public Page<UserVo> pageList(UserBo user, PageQuery query) {
        Page<UserVo> list = userMapper.pageList(user, query.build());
        return list;
    }

Mapper

    Page<UserVo> pageList(@Param("ew")UserBo bo,Page<User> page);

Mapper.xml

    <select id="pageList" resultMap="userResultMap">
        SELECT * FROM user
    </select>

这里不要加;不然会导致后面的分页条件加不上去报错

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值