当前位置: 首页 > article >正文

MybatisPlus从入门到精通

一、MyBatis-Plus特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、快速入门案例

1. 数据库准备

DROP TABLE IF EXISTS sys_user;

CREATE TABLE sys_user
(
	id BIGINT NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);
DELETE FROM sys_user;

INSERT INTO sys_user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2. Spring Boot配置

pom.xml依赖

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.3</version>
        </dependency>

application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
    username: root
    password: root

3. 实体类与Mapper

package com.awei.mybatismodel.entity;

import lombok.Data;

@Data
public class SysUser {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

package com.awei.mybatismodel.mapper;


import com.awei.mybatismodel.entity.SysUser;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface SysUserMapper extends BaseMapper<SysUser> {

}

4.启动类

package com.awei.mybatismodel;

import org.springframework.boot.SpringApplication;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.awei.mybatismodel.mapper")
public class MybatisModelApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisModelApplication.class, args);
    }

}

5.测试

package com.awei.mybatismodel;

import com.awei.mybatismodel.entity.SysUser;
import com.awei.mybatismodel.mapper.SysUserMapper;
import org.junit.jupiter.api.Assertions;
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
public class QuickStartTest {

    @Autowired
    private SysUserMapper userMapper;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<SysUser> userList = userMapper.selectList(null);
        Assertions.assertEquals(5, userList.size());
        userList.forEach(System.out::println);
    }
}

在这里插入图片描述

三、核心注解详解

注解作用示例
@TableName指定实体类对应的表名@TableName("sys_user")
@TableId标识主键字段@TableId(type = IdType.AUTO)
@TableField字段与列映射/自动填充策略@TableField(value = "email", fill = FieldFill.INSERT_UPDATE)

主键策略示例

public enum IdType {
    AUTO,        // 数据库自增
    ASSIGN_ID,   // 雪花算法(默认)
    ASSIGN_UUID  // UUID生成
}

四、CRUD操作Service Interface

1. 准备数据

CREATE TABLE user
(
	id BIGINT NOT NULL COMMENT '主键ID',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
	PRIMARY KEY (id)
);

User.java

package com.awei.mybatismodel.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
@TableName("user")
public class User {

    private Long id;
    private String name;
    private Integer age;
    private String email;
    @TableField(exist = false)
    private String ignoreColumn = "ignoreColumn";

    @TableField(exist = false)
    private Integer count;
}

UserMapper

public interface UserMapper extends BaseMapper<User> {

}

UserService

public interface UserService extends IService<User> {

}

UserServiceImpl

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
}

2.save

@SpringBootTest
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void saveTest() {
        // 假设有一个 User 实体对象
        User user = new User();
        user.setName("John Doe");
        user.setEmail("john.doe@example.com");
        boolean result = userService.save(user); // 调用 save 方法
        if (result) {
            System.out.println("User saved successfully.");
        } else {
            System.out.println("Failed to save user.");
        }
    }
}

在这里插入图片描述
示例(saveBatch):

@Test
    public void saveBatch() {
        // 假设有一组 User 实体对象
        List<User> users = Arrays.asList(
                new User("Alice", "alice@example.com"),
                new User("Bob", "bob@example.com"),
                new User("Charlie", "charlie@example.com")
        );
        // 使用默认批次大小进行批量插入
        boolean result = userService.saveBatch(users); // 调用 saveBatch 方法,默认批次大小
        if (result) {
            System.out.println("Users saved successfully.");
        } else {
            System.out.println("Failed to save users.");
        }
    }

在这里插入图片描述
示例(saveBatch 指定批次大小):

// 假设有一组 User 实体对象
List<User> users = Arrays.asList(
    new User("David", "david@example.com"),
    new User("Eve", "eve@example.com"),
    new User("Frank", "frank@example.com"),
    new User("Grace", "grace@example.com")
);
// 指定批次大小为 2进行批量插入
boolean result = userService.saveBatch(users, 2); // 调用 saveBatch 方法,指定批次大小
if (result) {
    System.out.println("Users saved successfully.");
} else {
    System.out.println("Failed to save users.");
}

生成的 SQL(指定批次大小为 2):

-- 第一批次
INSERT INTO user (name, email) VALUES
('David', 'david@example.com'),
('Eve', 'eve@example.com')

-- 第二批次
INSERT INTO user (name, email) VALUES
('Frank', 'frank@example.com'),
('Grace', 'grace@example.com')

通过上述示例,我们可以看到 save 系列方法是如何在 Service 层进行批量插入操作的,以及它们对应的 SQL 语句。这些方法大大简化了插入操作的代码编写,提高了开发效率。

3.saveOrUpdate

// TableId 注解属性值存在则更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

功能描述: 根据实体对象的主键 ID 进行判断,存在则更新记录,否则插入记录。
返回值: boolean,表示插入或更新操作是否成功。
参数说明:

类型 |参数名 |描述
T | entity | 实体对象
Wrapper updateWrapper 实体对象封装操作类 UpdateWrapper
Collection entityList 实体对象集合
int batchSize 插入批次数量

示例(saveOrUpdate):

// 假设有一个 User 实体对象,其中 id 是 TableId 注解的属性
User user = new User();
user.setId(1897283538508918787L);
user.setName("John Doe");
user.setEmail("john.doe@example.com");
boolean result = userService.saveOrUpdate(user); // 调用 saveOrUpdate 方法
if (result) {
    System.out.println("User updated or saved successfully.");
} else {
    System.out.println("Failed to update or save user.");
}

生成的 SQL(假设 id 为 1 的记录已存在):

UPDATE user SET name = 'John Doe', email = 'john.doe@example.com' WHERE id = 1

生成的 SQL(假设 id 为 1 的记录不存在):

INSERT INTO user (id, name, email) VALUES (1, 'John Doe', 'john.doe@example.com')

示例(saveOrUpdateBatch):

// 假设有一组 User 实体对象,每个对象都有 id 属性
List<User> users = Arrays.asList(
    new User(1, "Alice", "alice@example.com"),
    new User(2, "Bob", "bob@example.com"),
    new User(3, "Charlie", "charlie@example.com")
);
// 使用默认批次大小进行批量修改插入
boolean result = userService.saveOrUpdateBatch(users); // 调用 saveOrUpdateBatch 方法,默认批次大小
if (result) {
    System.out.println("Users updated or saved successfully.");
} else {
    System.out.println("Failed to update or save users.");
}

生成的 SQL(假设 id 为 1 和 2 的记录已存在,id 为 3 的记录不存在):

UPDATE user SET name = 'Alice', email = 'alice@example.com' WHERE id = 1
UPDATE user SET name = 'Bob', email = 'bob@example.com' WHERE id = 2
INSERT INTO user (id, name, email) VALUES (3, 'Charlie', 'charlie@example.com')

示例(saveOrUpdateBatch 指定批次大小):

// 假设有一组 User 实体对象
List<User> users = Arrays.asList(
    new User(4, "David", "david@example.com"),
    new User(5, "Eve", "eve@example.com"),
    new User(6, "Frank", "frank@example.com")
);
// 指定批次大小为 2进行批量修改插入
boolean result = userService.saveOrUpdateBatch(users, 2); // 调用 saveOrUpdateBatch 方法,指定批次大小
if (result) {
    System.out.println("Users updated or saved successfully.");
} else {
    System.out.println("Failed to update or save users.");
}

生成的 SQL(假设指定批次大小为 2):

-- 第一批次
UPDATE user SET name = 'David', email = 'david@example.com' WHERE id = 4
UPDATE user SET name = 'Eve', email = 'eve@example.com' WHERE id = 5

-- 第二批次
INSERT INTO user (id, name, email) VALUES (6, 'Frank', 'frank@example.com')

通过上述示例,我们可以看到 saveOrUpdate 系列方法是如何在 Service 层进行批量修改插入操作的,以及它们对应的 SQL 语句。这些方法提供了高效的数据操作方式,可以根据不同的条件进行更新或插入操作。

4.remove

// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

功能描述: 通过指定条件删除符合条件的记录。
返回值: boolean,表示删除操作是否成功。
参数说明:

类型参数名描述
WrapperqueryWrapper实体包装类 QueryWrapper
Serializableid主键 ID
Map<String, Object>columnMap表字段 map 对象
Collection<? extends Serializable>idList主键 ID 列表

示例(remove):

// 假设有一个 QueryWrapper 对象,设置删除条件为 name = 'John Doe'
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John Doe");
boolean result = userService.remove(queryWrapper); // 调用 remove 方法
if (result) {
    System.out.println("Record deleted successfully.");
} else {
    System.out.println("Failed to delete record.");
}

在这里插入图片描述
生成的 SQL:

DELETE FROM user WHERE name = 'John Doe'

示例(removeById):

// 假设要删除 ID 为 1 的用户
boolean result = userService.removeById(1); // 调用 removeById 方法
if (result) {
    System.out.println("User deleted successfully.");
} else {
    System.out.println("Failed to delete user.");
}

生成的 SQL:

DELETE FROM user WHERE id = 1

示例(removeByMap):

// 假设有一个 columnMap,设置删除条件为 age = 30
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("age", 30);
boolean result = userService.removeByMap(columnMap); // 调用 removeByMap 方法
if (result) {
    System.out.println("Records deleted successfully.");
} else {
    System.out.println("Failed to delete records.");
}

生成的 SQL:

DELETE FROM user WHERE age = 30

示例(removeByIds):

// 假设有一组 ID 列表,批量删除用户
List<Integer> ids = Arrays.asList(1, 2, 3);
boolean result = userService.removeByIds(ids); // 调用 removeByIds 方法
if (result) {
    System.out.println("Users deleted successfully.");
} else {
    System.out.println("Failed to delete users.");
}

生成的 SQL:

DELETE FROM user WHERE id IN (1, 2, 3)

通过上述示例,我们可以看到 remove 系列方法是如何在 Service 层进行删除操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据操作方式,可以根据不同的条件进行删除操作。

5.update

// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

功能描述: 通过指定条件更新符合条件的记录。
返回值: boolean,表示更新操作是否成功。
参数说明:

类型参数名描述
WrapperupdateWrapper实体对象封装操作类 UpdateWrapper
Tentity实体对象
CollectionentityList实体对象集合
intbatchSize更新批次数量

示例(update UpdateWrapper 形式):

// 假设有一个 UpdateWrapper 对象,设置更新条件为 name = 'John Doe',更新字段为 email
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name", "John Doe").set("email", "john.doe@newdomain.com");
boolean result = userService.update(updateWrapper); // 调用 update 方法
if (result) {
    System.out.println("Record updated successfully.");
} else {
    System.out.println("Failed to update record.");
}

生成的 SQL:

UPDATE user SET email = 'john.doe@newdomain.com' WHERE name = 'John Doe'

示例(update WhereWrapper 形式):

// 假设有一个 User 实体对象,设置更新字段为 name,以及一个 whereWrapper 设置更新条件为 id = 1
User updateEntity = new User();
updateEntity.setName("Updated Name");
QueryWrapper<User> whereWrapper = new QueryWrapper<>();
whereWrapper.eq("id", 1);
boolean result = userService.update(updateEntity, whereWrapper); // 调用 update 方法
if (result) {
    System.out.println("Record updated successfully.");
} else {
    System.out.println("Failed to update record.");
}

生成的 SQL:

UPDATE user SET name = 'Updated Name' WHERE id = 1

示例(updateById):

// 假设有一个 User 实体对象,设置更新字段为 email,根据 ID 更新
User updateEntity = new User();
updateEntity.setId(1);
updateEntity.setEmail("updated.email@example.com");
boolean result = userService.updateById(updateEntity); // 调用 updateById 方法
if (result) {
    System.out.println("Record updated successfully.");
} else {
    System.out.println("Failed to update record.");
}

生成的 SQL:

UPDATE user SET email = 'updated.email@example.com' WHERE id = 1

示例(updateBatchById):

// 假设有一组 User 实体对象,批量更新
List<User> users = Arrays.asList(
    new User(1, null, "new.email1@example.com"),
    new User(2, null, "new.email2@example.com")
);
boolean result = userService.updateBatchById(users); // 调用 updateBatchById 方法,默认批次大小
if (result) {
    System.out.println("Records updated successfully.");
} else {
    System.out.println("Failed to update records.");
}

生成的 SQL(假设默认批次大小为 2):

UPDATE user SET email = 'new.email1@example.com' WHERE id = 1
UPDATE user SET email = 'new.email2@example.com' WHERE id = 2

示例(updateBatchById 指定批次大小):

// 假设有一组 User 实体对象,批量更新,并指定批次大小为 1
List<User> users = Arrays.asList(
    new User(1, null, "new.email1@example.com"),
    new User(2, null, "new.email2@example.com")
);
boolean result = userService.updateBatchById(users, 1); // 调用 updateBatchById 方法,指定批次大小
if (result) {
    System.out.println("Records updated successfully.");
} else {
    System.out.println("Failed to update records.");
}

生成的 SQL(假设指定批次大小为 1):

-- 第一批次
UPDATE user SET email = 'new.email1@example.com' WHERE id = 1
-- 第二批次
UPDATE user SET email = 'new.email2@example.com' WHERE id = 2

通过上述示例,我们可以看到 update 系列方法是如何在 Service 层进行更新操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据操作方式,可以根据不同的条件进行更新操作。

get

// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

功能描述: 根据指定条件查询符合条件的记录。
返回值: 查询结果,可能是实体对象、Map 对象或其他类型。
参数说明:

类型参数名描述
Serializableid主键 ID
WrapperqueryWrapper实体对象封装操作类 QueryWrapper
booleanthrowEx有多个 result 是否抛出异常
Tentity实体对象
Function<? super Object, V>mapper转换函数

示例(getById):

// 假设要查询 ID 为 1 的用户
User user = userService.getById(1); // 调用 getById 方法
if (user != null) {
    System.out.println("User found: " + user);
} else {
    System.out.println("User not found.");
}

生成的 SQL:

SELECT * FROM user WHERE id = 1

示例(getOne):

// 假设有一个 QueryWrapper 对象,设置查询条件为 name = 'John Doe'
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John Doe");
User user = userService.getOne(queryWrapper); // 调用 getOne 方法
if (user != null) {
    System.out.println("User found: " + user);
} else {
    System.out.println("User not found.");
}

生成的 SQL:

SELECT * FROM user WHERE name = 'John Doe'

示例(getOne 不抛出异常):

// 假设有一个 QueryWrapper 对象,设置查询条件为 name = 'John Doe',并且不抛出异常
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John Doe");
User user = userService.getOne(queryWrapper, false); // 调用 getOne 方法
if (user != null) {
    System.out.println("User found: " + user);
} else {
    System.out.println("User not found.");
}

生成的 SQL:

SELECT * FROM user WHERE name = 'John Doe'
示例(getMap):
// 假设有一个 QueryWrapper 对象,设置查询条件为 name = 'John Doe',并将结果映射为 Map
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John Doe");
Map<String, Object> userMap = userService.getMap(queryWrapper); // 调用 getMap 方法
if (userMap != null) {
    System.out.println("User found: " + userMap);
} else {
    System.out.println("User not found.");
}

生成的 SQL:

SELECT * FROM user WHERE name = 'John Doe'

示例(getObj):

// 假设有一个 QueryWrapper 对象,设置查询条件为 name = 'John Doe',并将结果转换为 String
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John Doe");
String userName = userService.getObj(queryWrapper, obj -> ((User) obj).getName()); // 调用 getObj 方法
if (userName != null) {
    System.out.println("User name found: " + userName);
} else {
    System.out.println("User name not found.");
}

生成的 SQL:

SELECT * FROM user WHERE name = 'John Doe'

通过上述示例,我们可以看到 get 系列方法是如何在 Service 层进行查询操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据查询方式,可以根据不同的条件进行查询操作。

list

// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

功能描述: 查询符合条件的记录。
返回值: 查询结果,可能是实体对象、Map 对象或其他类型。
参数说明:

类型参数名描述
WrapperqueryWrapper实体对象封装操作类 QueryWrapper
Collection<? extends Serializable>idList主键ID列表
Map<String, Object>columnMap表字段 map对象
Function<? super Object, V>mapper转换函数

示例(list):

// 查询所有用户
List<User> users = userService.list(); // 调用 list 方法
for (User user : users) {
    System.out.println("User: " + user);
}

生成的 SQL:

SELECT * FROM user
示例(list QueryWrapper 形式):
// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
List<User> users = userService.list(queryWrapper); // 调用 list 方法
for (User user : users) {
    System.out.println("User: " + user);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25
示例(listByIds):
// 假设有一组 ID 列表,批量查询用户
List<Integer> ids = Arrays.asList(1, 2, 3);
Collection<User> users = userService.listByIds(ids); // 调用 listByIds 方法
for (User user : users) {
    System.out.println("User: " + user);
}

生成的 SQL:

SELECT * FROM user WHERE id IN (1, 2, 3)

示例(listByMap):

// 假设有一个 columnMap,设置查询条件为 age = 30
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("age", 30);
Collection<User> users = userService.listByMap(columnMap); // 调用 listByMap 方法
for (User user : users) {
    System.out.println("User: " + user);
}

生成的 SQL:

SELECT * FROM user WHERE age = 30
示例(listMaps):
// 查询所有用户,并将结果映射为 Map
List<Map<String, Object>> userMaps = userService.listMaps(); // 调用 listMaps 方法
for (Map<String, Object> userMap : userMaps) {
    System.out.println("User Map: " + userMap);
}

生成的 SQL:

SELECT * FROM user
User Map: {name=Updated Name, id=1, email=alice@example.com}
User Map: {name=Bob, id=1897282952199778306, email=bob@example.com}
User Map: {name=Charlie, id=1897282952199778307, email=charlie@example.com}
User Map: {name=David, id=1897283538441809921, email=david@example.com}
User Map: {name=John Doe, id=1897283538508918785, email=john.doe@newdomain.com}
User Map: {name=John Doe, id=1897292359369265154, email=john.doe@example.com}

示例(listMaps QueryWrapper 形式):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,并将结果映射为 Map
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
List<Map<String, Object>> userMaps = userService.listMaps(queryWrapper); // 调用 listMaps 方法
for (Map<String, Object> userMap : userMaps) {
    System.out.println("User Map: " + userMap);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25

示例(listObjs):

// 查询所有用户,并将结果转换为 String 列表
List<String> userNames = userService.listObjs(obj -> ((User) obj).getName()); // 调用 listObjs 方法
for (String userName : userNames) {
    System.out.println("User Name: " + userName);
}

生成的 SQL:

SELECT * FROM user
示例(listObjs QueryWrapper 形式):
// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,并将结果转换为 String 列表
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
List<String> userNames = userService.listObjs(queryWrapper, obj -> ((User) obj).getName()); // 调用 listObjs 方法
for (String userName : userNames) {
    System.out.println("User Name: " + userName);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25

通过上述示例,我们可以看到 list 系列方法是如何在 Service 层进行查询操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据查询方式,可以根据不同的条件进行查询操作。

五、分页查询page

配置分页·分页插件

@Configuration
public class MybatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

分页方法

// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

功能描述: 分页查询符合条件的记录。
返回值: 分页查询结果,包含记录列表和总记录数。
参数说明:

类型参数名描述
IPagepage翻页对象
WrapperqueryWrapper实体对象封装操作类 QueryWrapper

示例(page):

// 假设要进行无条件的分页查询,每页显示10条记录,查询第1页
IPage<User> page = new Page<>(1, 10);
IPage<User> userPage = userService.page(page); // 调用 page 方法
List<User> userList = userPage.getRecords();
long total = userPage.getTotal();
System.out.println("Total users: " + total);
for (User user : userList) {
    System.out.println("User: " + user);
}

生成的 SQL:

SELECT * FROM user LIMIT 10 OFFSET 0

示例(page QueryWrapper 形式):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,进行有条件的分页查询
IPage<User> page = new Page<>(1, 10);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
IPage<User> userPage = userService.page(page, queryWrapper); // 调用 page 方法
List<User> userList = userPage.getRecords();
long total = userPage.getTotal();
System.out.println("Total users (age > 25): " + total);
for (User user : userList) {
    System.out.println("User: " + user);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25 LIMIT 10 OFFSET 0

示例(pageMaps):

// 假设要进行无条件的分页查询,并将结果映射为 Map,每页显示10条记录,查询第1页
IPage<Map<String, Object>> page = new Page<>(1, 10);
IPage<Map<String, Object>> userPageMaps = userService.pageMaps(page); // 调用 pageMaps 方法
List<Map<String, Object>> userMapList = userPageMaps.getRecords();
long total = userPageMaps.getTotal();
System.out.println("Total users: " + total);
for (Map<String, Object> userMap : userMapList) {
    System.out.println("User Map: " + userMap);
}

生成的 SQL:

SELECT * FROM user LIMIT 10 OFFSET 0

运行结果

Total users: 6
User Map: {name=Updated Name, id=1, age=21, email=alice@example.com}
User Map: {name=Bob, id=1897282952199778306, age=22, email=bob@example.com}
User Map: {name=Charlie, id=1897282952199778307, age=23, email=charlie@example.com}
User Map: {name=David, id=1897283538441809921, age=20, email=david@example.com}
User Map: {name=John Doe, id=1897283538508918785, age=19, email=john.doe@newdomain.com}
User Map: {name=John Doe, id=1897292359369265154, age=18, email=john.doe@example.com}

示例(pageMaps QueryWrapper 形式):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,进行有条件的分页查询,并将结果映射为 Map
IPage<Map<String, Object>> page = new Page<>(1, 10);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
IPage<Map<String, Object>> userPageMaps = userService.pageMaps(page, queryWrapper); // 调用 pageMaps 方法
List<Map<String, Object>> userMapList = userPageMaps.getRecords();
long total = userPageMaps.getTotal();
System.out.println("Total users (age > 25): " + total);
for (Map<String, Object> userMap : userMapList) {
    System.out.println("User Map: " + userMap);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25 LIMIT 10 OFFSET 0

通过上述示例,我们可以看到 page 系列方法是如何在 Service 层进行分页查询操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据查询方式,可以根据不同的条件进行分页查询操作。

六、count

// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

//自3.4.3.2开始,返回值修改为long
// 查询总记录数
long count();
// 根据 Wrapper 条件,查询总记录数
long count(Wrapper<T> queryWrapper);

功能描述: 查询符合条件的记录总数。
返回值: 符合条件的记录总数。
参数说明:

类型参数名描述
WrapperqueryWrapper实体对象封装操作类 QueryWrapper

示例(count):

// 查询用户表中的总记录数
int totalUsers = userService.count(); // 调用 count 方法
System.out.println("Total users: " + totalUsers);

生成的 SQL:

SELECT COUNT(*) FROM user

示例(count QueryWrapper 形式):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,查询满足条件的用户总数
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
int totalUsers = userService.count(queryWrapper); // 调用 count 方法
System.out.println("Total users (age > 25): " + totalUsers);

生成的 SQL:

SELECT COUNT(*) FROM user WHERE age > 25

通过上述示例,我们可以看到 count 方法是如何在 Service 层进行记录数统计操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据统计方式,可以根据不同的条件进行记录数统计。

七、增删改查 Mapper Interface

BaseMapper 是 Mybatis-Plus 提供的一个通用 Mapper 接口,它封装了一系列常用的数据库操作方法,包括增、删、改、查等。通过继承 BaseMapper,开发者可以快速地对数据库进行操作,而无需编写繁琐的 SQL 语句。

1.insert

// 插入一条记录
int insert(T entity);

功能描述: 插入一条记录。
返回值: int,表示插入操作影响的行数,通常为 1,表示插入成功。

示例(insert):

User user = new User();
user.setName("John Doe");
user.setEmail("john.doe@example.com");
int rows = userMapper.insert(user); // 调用 insert 方法
if (rows > 0) {
    System.out.println("User inserted successfully.");
} else {
    System.out.println("Failed to insert user.");
}

生成的 SQL:

INSERT INTO user (name, email) VALUES (?, ?)

通过上述示例,我们可以看到 insert 方法是如何在 Mapper 层进行插入操作的,以及它对应的 SQL 语句。这个方法简化了插入操作的实现,使得开发者无需手动编写 SQL 语句。

2. delete

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

功能描述: 删除符合条件的记录。
返回值: int,表示删除操作影响的行数,通常为 1,表示删除成功。
参数说明:

类型参数名描述
Wrapperwrapper实体对象封装操作类(可以为null)
Collection<? extends Serializable>idList主键ID列表(不能为空以及empty)
Serializableid主键ID
Map<String, Object>columnMap表字段map对象

示例(delete):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,删除满足条件的用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
int rows = userMapper.delete(queryWrapper); // 调用 delete 方法
if (rows > 0) {
    System.out.println("Users deleted successfully.");
} else {
    System.out.println("No users deleted.");
}

生成的 SQL:

DELETE FROM user WHERE age > 25

示例(deleteBatchIds):

// 假设有一组 ID 列表,批量删除用户
List<Integer> ids = Arrays.asList(1, 2, 3);
int rows = userMapper.deleteBatchIds(ids); // 调用 deleteBatchIds 方法
if (rows > 0) {
    System.out.println("Users deleted successfully.");
} else {
    System.out.println("No users deleted.");
}

生成的 SQL:

DELETE FROM user WHERE id IN (1, 2, 3)

示例(deleteById):

// 根据 ID 删除单个用户
int userId = 1;
int rows = userMapper.deleteById(userId); // 调用 deleteById 方法
if (rows > 0) {
    System.out.println("User deleted successfully.");
} else {
    System.out.println("No user deleted.");
}

生成的 SQL:

DELETE FROM user WHERE id = 1

示例(deleteByMap):

// 假设有一个 columnMap,设置查询条件为 age = 30,删除满足条件的用户
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("age", 30);
int rows = userMapper.deleteByMap(columnMap); // 调用 deleteByMap 方法
if (rows > 0) {
    System.out.println("Users deleted successfully.");
} else {
    System.out.println("No users deleted.");
}

生成的 SQL:

DELETE FROM user WHERE age = 30

通过上述示例,我们可以看到 delete 系列方法是如何在 Mapper 层进行删除操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据删除方式,可以根据不同的条件进行删除操作。

3. update

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);

功能描述: 更新符合条件的记录。
返回值: int,表示更新操作影响的行数,通常为 1,表示更新成功。
参数说明:

类型参数名描述
Tentity实体对象 (set条件值,可为null)
WrapperupdateWrapper实体对象封装操作类(可以为null,里面的entity用于生成where语句)

示例(update):

// 假设有一个 UpdateWrapper 对象,设置查询条件为 age > 25,更新满足条件的用户的邮箱
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.gt("age", 25);
User updateUser = new User();
updateUser.setEmail("new.email@example.com");
int rows = userMapper.update(updateUser, updateWrapper); // 调用 update 方法
if (rows > 0) {
    System.out.println("Users updated successfully.");
} else {
    System.out.println("No users updated.");
}

生成的 SQL:

UPDATE user SET email = ? WHERE age > 25

示例(updateById):

// 假设要更新 ID 为 1 的用户的邮箱
User updateUser = new User();
updateUser.setId(1);
updateUser.setEmail("new.email@example.com");
int rows = userMapper.updateById(updateUser); // 调用 updateById 方法
if (rows > 0) {
    System.out.println("User updated successfully.");
} else {
    System.out.println("No user updated.");
}

生成的 SQL:

UPDATE user SET email = ? WHERE id = 1

通过上述示例,我们可以看到 update 系列方法是如何在 Mapper 层进行更新操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据更新方式,可以根据不同的条件进行更新操作。

4. select

// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

功能描述: 查询符合条件的记录。
返回值: 查询结果,可能是实体对象、Map 对象或其他类型。
参数说明:

类型参数名描述
Serializableid主键ID
WrapperqueryWrapper实体对象封装操作类(可以为null)
Collection<? extends Serializable>idList主键ID列表(不能为空以及empty)
Map<String, Object>columnMap表字段map对象
IPagepage分页查询条件(可以为RowBounds.DEFAULT)

示例(selectById):

// 根据 ID 查询单个用户
int userId = 1;
User user = userMapper.selectById(userId); // 调用 selectById 方法
System.out.println("User: " + user);

生成的 SQL:

SELECT * FROM user WHERE id = 1

示例(selectOne):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,查询一条满足条件的用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
User user = userMapper.selectOne(queryWrapper); // 调用 selectOne 方法
System.out.println("User: " + user);

生成的 SQL:

SELECT * FROM user WHERE age > 25

示例(selectBatchIds):

// 假设有一组 ID 列表,批量查询用户
List<Integer> ids = Arrays.asList(1, 2, 3);
List<User> users = userMapper.selectBatchIds(ids); // 调用 selectBatchIds 方法
for (User u : users) {
    System.out.println("User: " + u);
}

生成的 SQL:

SELECT * FROM user WHERE id IN (1, 2, 3)

示例(selectList):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,查询所有满足条件的用户
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
List<User> users = userMapper.selectList(queryWrapper); // 调用 selectList 方法
for (User u : users) {
    System.out.println("User: " + u);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25

示例(selectByMap):

// 假设有一个 columnMap,设置查询条件为 age > 30,查询满足条件的用户
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("age", 30);
List<User> users = userMapper.selectByMap(columnMap); // 调用 selectByMap 方法
for (User u : users) {
    System.out.println("User: " + u);
}

生成的 SQL:

SELECT * FROM user WHERE age > 30

示例(selectMaps):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,查询所有满足条件的用户,并将结果映射为 Map
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
List<Map<String, Object>> userMaps = userMapper.selectMaps(queryWrapper); // 调用 selectMaps 方法
for (Map<String, Object> userMap : userMaps) {
    System.out.println("User Map: " + userMap);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25

示例(selectObjs):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,查询所有满足条件的用户,但只返回每个记录的第一个字段的值
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
List<Object> userIds = userMapper.selectObjs(queryWrapper); // 调用 selectObjs 方法
for (Object userId : userIds) {
    System.out.println("User ID: " + userId);
}

生成的 SQL:

SELECT id FROM user WHERE age > 25

示例(selectPage):

// 假设要进行分页查询,每页显示10条记录,查询第1页,查询条件为 age > 25
IPage<User> page = new Page<>(1, 10);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
IPage<User> userPage = userMapper.selectPage(page, queryWrapper); // 调用 selectPage 方法
List<User> userList = userPage.getRecords();
long total = userPage.getTotal();
System.out.println("Total users (age > 25): " + total);
for (User user : userList) {
    System.out.println("User: " + user);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25 LIMIT 10 OFFSET 0

示例(selectMapsPage):

// 假设要进行分页查询,每页显示10条记录,查询第1页,查询条件为 age > 25,并将结果映射为 Map
IPage<Map<String, Object>> = new Page<>(1, 10);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
IPage<Map<String, Object>> userPageMaps = userMapper.selectMapsPage(page, queryWrapper); // 调用 selectMapsPage 方法
List<Map<String, Object>> userMapList = userPageMaps.getRecords();
long total = userPageMaps.getTotal();
System.out.println("Total users (age > 25): " + total);
for (Map<String, Object> userMap : userMapList) {
    System.out.println("User Map: " + userMap);
}

生成的 SQL:

SELECT * FROM user WHERE age > 25 LIMIT 10 OFFSET 0

示例(selectCount):

// 假设有一个 QueryWrapper 对象,设置查询条件为 age > 25,查询总记录数
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 25);
Integer totalUsers = userMapper.selectCount(queryWrapper); // 调用 selectCount 方法
System.out.println("Total users (age > 25): " + totalUsers);

生成的 SQL:

SELECT COUNT(*) FROM user WHERE age > 25

通过上述示例,我们可以看到 select 系列方法是如何在 Mapper 层进行查询操作的,以及它们对应的 SQL 语句。这些方法提供了灵活的数据查询方式,可以根据不同的条件进行查询操作,包括单条记录查询、批量查询、条件查询、分页查询等。

八、高级查询——条件构造器

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 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。

1.allEq

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

使用范围
QueryWrapper
LambdaQueryWrapper
UpdateWrapper
LambdaUpdateWrapper
方法签名

// 设置所有字段的相等条件,如果字段值为null,则根据null2IsNull参数决定是否设置为IS NULL
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:一个布尔值,用于控制是否应用这些条件。

示例

普通 Wrapper (QueryWrapper):

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.allEq(Map.of("id", 1, "name", "老王", "age", null));

Lambda Wrapper (LambdaQueryWrapper):

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.allEq(Map.of("id", 1, "name", "老王", "age", null));

带过滤器的普通 Wrapper (QueryWrapper):

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.allEq((field, value) -> field.contains("a"), Map.of("id", 1, "name", "老王", "age", null));

带过滤器的 Lambda Wrapper (LambdaQueryWrapper):

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.allEq((field, value) -> field.contains("a"), Map.of("id", 1, "name", "老王", "age", null));

生成的 SQL

-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE id = 1 AND name = '老王' AND age IS NULL

-- 带过滤器的普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE name = '老王' AND age IS NULL

测试类

@Test
    public void saveBatch() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        Map<String, Object> params = new HashMap<>();
        params.put("id", 1);
        params.put("name", "Updated Name");
        params.put("age", null);
        queryWrapper.allEq(params);
        List<User> users = userService.list(queryWrapper);
        for (User user : users) {
            System.out.println(user);
        }
User(id=1, name=Updated Name, age=null, email=alice@example.com, ignoreColumn=ignoreColumn, count=null)

2.eq

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

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

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

参数说明

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

普通 Wrapper (QueryWrapper):

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "老王");

Lambda Wrapper (LambdaQueryWrapper):

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getName, "老王");

生成的 SQL

-- 普通 WrapperLambda Wrapper 生成的 SQL 相同
SELECT * FROM user WHERE name = '老王'

3.其他条件

	AND("AND"),
    OR("OR"),
    NOT("NOT"),
    IN("IN"),
    NOT_IN("NOT IN"),
    LIKE("LIKE"),
    NOT_LIKE("NOT LIKE"),
    EQ("="),
    NE("<>"),
    GT(">"),
    GE(">="),
    LT("<"),
    LE("<="),
    IS_NULL("IS NULL"),
    IS_NOT_NULL("IS NOT NULL"),
    GROUP_BY("GROUP BY"),
    HAVING("HAVING"),
    ORDER_BY("ORDER BY"),
    EXISTS("EXISTS"),
    NOT_EXISTS("NOT EXISTS"),
    BETWEEN("BETWEEN"),
    NOT_BETWEEN("NOT BETWEEN"),
    ASC("ASC"),
    DESC("DESC");

九.逻辑删除

逻辑删除是一种优雅的数据管理策略,它通过在数据库中标记记录为“已删除”而非物理删除,来保留数据的历史痕迹,同时确保查询结果的整洁性。MyBatis-Plus 提供了便捷的逻辑删除支持,使得这一策略的实施变得简单高效。

逻辑删除的工作原理
MyBatis-Plus 的逻辑删除功能会在执行数据库操作时自动处理逻辑删除字段。以下是它的工作方式:

  • 插入:逻辑删除字段的值不受限制。
  • 查找:自动添加条件,过滤掉标记为已删除的记录。
  • 更新:防止更新已删除的记录。
  • 删除:将删除操作转换为更新操作,标记记录为已删除。

例如:

删除:update user set deleted=1 where id = 1 and deleted=0
查找:select id,name,deleted from user where deleted=0

支持的数据类型
逻辑删除字段支持所有数据类型,但推荐使用 Integer、Boolean 或 LocalDateTime。 如果使用 datetime 类型,可以配置逻辑未删除值为 null(长度为4的字符串,在yaml中需使用转义符(单引号)包裹),已删除值可以使用函数如 now() 来获取当前时间。 如果使用 bigint 类型,可以配置逻辑未删除值为 0,已删除值可以使用函数如 UNIX_TIMESTAMP() 来获取当前时间戳作为删除标识。适合用于将删除字段作为唯一索引组成列,可以多次逻辑删除.

使用方法
步骤 1: 配置全局逻辑删除属性
在 application.yml 中配置 MyBatis-Plus 的全局逻辑删除属性:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除字段名
      logic-delete-value: 1 # 逻辑已删除值
      logic-not-delete-value: 0 # 逻辑未删除值

步骤 2: 在实体类中使用 @TableLogic 注解
在实体类中,对应数据库表的逻辑删除字段上添加 @TableLogic 注解:

import com.baomidou.mybatisplus.annotation.TableLogic;

public class User {
    // 其他字段...

    @TableLogic
    private Integer deleted;
}

十一.多数据源支持

配置数据源:

spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx)
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver

使用 @DS 切换数据源:

@Service
@DS("slave")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  @Override
  @DS("slave_1")
  public List selectByCondition() {
    return jdbcTemplate.queryForList("select * from user where age >10");
  }
}

http://www.kler.cn/a/573909.html

相关文章:

  • Linux基础 IO 和文件
  • Git安装与配置
  • 游戏树搜索与优化策略:Alpha-Beta剪枝及其实例分析
  • AI自动化应用的影响
  • IDC权威认证!永洪科技入选 IDC「GBI图谱」,点亮生成式 BI 价值灯塔
  • Redis的CPU高达90%时如何处理
  • STM32G030F6P6详细解读
  • upload-labs靶场 1-21通关
  • Go 语言中 panic 和 recover 的代价:性能与设计的权衡
  • css的毛玻璃效果backdrop-filter: blur()
  • 力扣hot100刷题——栈
  • 【C++设计模式】第七篇:桥接模式(Bridge)
  • Windows 10/11 系统下 Git 的详细安装步骤和基础设置指南
  • Power Settings Explorer官网下载地址: Windows电源选项设置管理工具
  • OSI七层网络结构和TCP/IP四层结构
  • 文件上传和下载前后端交互逻辑
  • Echarts与Vue3中获取DOM节点可能出现的异常错误
  • Springboot + nacos + dubbo 实现微服务架构
  • JavaEE基础之- ajax
  • DeepSeek大模型+RAGFlow实战指南:构建知识驱动的智能问答系统