Mybatis Plus核心功能

一,条件构造器

1.1 介绍

image-20240714100821779


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

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

  • AbstractWrapper:这是一个抽象基类,提供了所有 Wrapper 类共有的方法和属性。它定义了条件构造的基本逻辑,包括字段(column)、值(value)、操作符(condition)等。所有的 QueryWrapper、UpdateWrapper、LambdaQueryWrapper 和 LambdaUpdateWrapper 都继承自 AbstractWrapper。
  • QueryWrapper:专门用于构造查询条件,支持基本的等于、不等于、大于、小于等各种常见操作。它允许你以链式调用的方式添加多个查询条件,并且可以组合使用 andor 逻辑。
  • UpdateWrapper:用于构造更新条件,可以在更新数据时指定条件。与 QueryWrapper 类似,它也支持链式调用和逻辑组合。使用 UpdateWrapper 可以在不创建实体对象的情况下,直接设置更新字段和条件。
  • LambdaQueryWrapper:这是一个基于 Lambda 表达式的查询条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名。这种方式提高了代码的可读性和可维护性,尤其是在字段名可能发生变化的情况下。
  • LambdaUpdateWrapper:类似于 LambdaQueryWrapper,LambdaUpdateWrapper 是基于 Lambda 表达式的更新条件构造器。它允许你使用 Lambda 表达式来指定更新字段和条件,同样避免了硬编码字段名的问题。

1.2 使用方法

@Test
public void testSelect() {
    System.out.println(("----- selectAll method test ------"));
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","wdadwa");
    List<User> userList = userMapper.selectList(wrapper);
    userList.forEach(System.out::println);
}

上述构建了一个条件构造器,然后我们将条件构造器传入select即可实现条件查询

上述代码等效于:

select * from user where name='wdadwa'

1.2.1 MybatisPlus基础查询条件的方法

  • allEq:允许我们通过一个 Map 来设置多个字段的相等条件。
  • eq:用于设置单个字段的相等条件
  • ne:用于设置单个字段的不相等条件。
  • gt:用于设置单个字段的大于条件。
  • ge:用于设置单个字段的大于等于条件。
  • It:用于设置单个字段的小于条件
  • Ie:用于设置单个字段的小于等于条件。
  • between:用于设置单个字段的 BETWEEN 条件。
  • notBetween:用于设置单个字段的NOT BETWEEN条件。
  • like:用于设置单个字段的 LIKE 条件。
  • notLike:用于设置单个字段的 NOT LIKE 条件。
  • likeLeft:用于设置单个字段的模糊匹配条件。
  • likeRight:用于设置单个字段的模糊匹配条件。
  • notLikeLeft:用于设置单个字段的非左模糊匹配条件。
  • notLikeRihgt:用于设置单个字段的非右模糊匹配条件。
  • isNull:用于设置单个字段的IS NULL条件。
  • in:用于设置单个字段的IN条件,即字段的值在给定的集合中。
  • notIn:用于设置单个字段的 NOT IN 条件,即字段的值不在给定的集合中。
  • groupBy:用于设置查询结果的分组条件。
  • having:它用于设置HAVING子句,通常与GROUP BY一起使用,用于对分组后的数据进行条件筛选。
  • orderByAsc:用于设置查询结果的升序排序条件
  • orderByDesc:用于设置查询结果的降序排序条件
  • orderBy:用于设置查询结果的排序条件。
  • or:用于在查询条件中添加 OR 逻辑。
  • and:用于在查询条件中添加 AND 逻辑。
  • select:用于设置查询的字段。通过调用 select 方法,可以指定在查询结果中包含哪些字段,从而实现字段级别的查询定制。
  • set:用于设置更新语句中的SET字段。通过调用 set 方法,可以指定在更新操作中要修改的字段及其新值。
  • setIncrBy:允许你指定一个字段,并使其在数据库中的值增加指定的数值。
  • setDecrBy:允许你指定一个字段,并使其在数据库中的值减少指定的数值

1.2.2 LambdaWrapper和普通Wrapper的区别

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.lt("age", 18);

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.lt(User::getAge, 18);

一个通过方法引用的方式将字段传入,一个通过String硬编码将字段传入。


1.2.3 MybatisPlus构建复杂SQL

不推荐这种使用方式,MybatisPlus只推荐使用简单的单表crud,这种复杂的建议直接写到xml用Mybatis的方式来编写。本节了解即可。

举例:

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eqSql("id", "select MAX(id) from table");

等效于:

SELECT * FROM user WHERE id = (select MAX(id) from table)

所有的方法有:

  • inSql:用于设置单个字段的 IN 条件
  • notInSql:用于设置单个字段的 NOT IN 条件
  • eqSql:允许你设置一个字段等于(EQ)某个 SQL 语句的结果
  • gtSql:允许你设置一个字段大于(GT)某个 SQL 语句的结果。
  • geSql:允许你设置一个字段大于等于(GE)某个 SQL 语句的结果。
  • ItSql:允许你设置一个字段小于(LT)某个 SQL 语句的结果。
  • IeSql:允许你设置一个字段小于等于(LE)某个 SQL 语句的结果。
  • nested:构建子查询
  • apply:允许你直接拼接 SQL 片段到查询条件中。
  • last:允许你直接在查询的最后添加一个 SQL 片段,而不受 MyBatis-Plus 的查询优化规则影响
  • exists:用于在查询中添加一个 EXISTS 子查询
  • notExists:用于在查询中添加一个NOT EXISTS子查询
  • setSql:允许你直接设置更新语句中的SET部分 SQL。通

1.3 Wrappers

MyBatis-Plus 提供了 Wrappers 类,它是一个静态工厂类,用于快速创建 QueryWrapperUpdateWrapperLambdaQueryWrapperLambdaUpdateWrapper 的实例。

使用 Wrappers 可以减少代码量,提高开发效率。

举例:

// 创建 QueryWrapper
QueryWrapper<User> queryWrapper = Wrappers.query();
queryWrapper.eq("name", "张三");

// 创建 LambdaQueryWrapper
LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
lambdaQueryWrapper.eq(User::getName, "张三");

// 创建 UpdateWrapper
UpdateWrapper<User> updateWrapper = Wrappers.update();
updateWrapper.set("name", "李四");

// 创建 LambdaUpdateWrapper
LambdaUpdateWrapper<User> lambdaUpdateWrapper = Wrappers.lambdaUpdate();
lambdaUpdateWrapper.set(User::getName, "李四");

1.4 注意点

通过使用 MyBatis-Plus 的 Wrappers 条件构造器,开发者可以更加高效地构建复杂的数据库查询条件,同时保持代码的简洁性和安全性。

  • 在使用 Wrapper 时,尽量使用 Lambda 表达式来避免硬编码字段名,这样可以提高代码的可读性和可维护性。Wrapper 支持链式调用,可以组合多个条件,如 and、or 等逻辑操作符。
  • 在更新操作中使用 UpdateWrapper 或 LambdaUpdateWrapper 时,可以省略实体对象,直接在 Wrapper 中设置更新字段。
  • 注意 Wrapper 的线程安全性,通常在每次使用时创建新的 Wrapper 实例。
  • 在使用 MyBatis-Plus 的 Wrapper 时,应避免将前端动态参数直接拼接到 SQL 片段中,以防止 SQL 注入攻击。MyBatis-Plus 提供了安全的参数绑定方式,如使用 eq、apply 等方法,它们会自动处理参数绑定,避免 SQL 注入风险。
  • 不推荐在MybatisPlus构建过于复杂的SQL,不便于维护。
  • 每个方法的具体使用可以看官方文档:https://baomidou.com/guides/wrapper/#功能详解

二,自定义SQL

我们可以用MyBatisPlus的Wrapper来构建复杂Where条件,然后自己定义SQL语句中剩下的部分:
image

三,Service接口

如下图,我们的接口要继承IService接口,我们的实现类要继承ServiceImpl然后实现自己的接口。
image

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

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

3.1 配置方法

  • 接口

    public interface IDemoService extends IService<User> {
    }
    
  • 实现类

    @Service
    public class DemoServiceImpl extends ServiceImpl<UserMapper, User> implements IDemoService {
    }
    

    两个泛型,一个是Mapper接口,一个是User类

3.2 save

功能描述: 插入记录,根据实体对象的字段进行策略性插入。

返回值: boolean,表示插入操作是否成功

参数说明

  • entity:实体类对象
  • entityList:实体类集合对象
  • batchSize:插入批次数量
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)(指定批次大小)
boolean saveBatch(Collection<T> entityList, int batchSize);

3.3 saveOrUpdate

功能描述: 根据实体对象的主键 ID 进行判断,存在则更新记录,否则插入记录。

返回值: boolean,表示插入或更新操作是否成功。

参数说明

  • entity:实体类对象
  • updateWrapper:实体对象封装操作类 UpdateWrapper
  • entityList:实体类集合对象
  • batchSize:插入批次数量
// 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);

3.4 remove

功能描述: 通过指定条件删除符合条件的记录。

返回值: boolean,表示删除操作是否成功。

参数说明

  • queryWrapper:实体包装类 QueryWrapper
  • id:主键 ID
  • columnMap:表字段 map 对象
  • idList:主键 ID 列表
// 根据 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);

3.5 update

功能描述: 通过指定条件更新符合条件的记录。

返回值: boolean,表示更新操作是否成功。

参数说明

  • updateWrapper:实体对象封装操作类 UpdateWrapper
  • entity:实体对象
  • entityList:实体对象集合
  • batchSize:更新批次数量
// 根据 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);

举例:

// 假设有一个 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'

3.6 get

功能描述: 根据指定条件查询符合条件的记录。

返回值: 查询结果,可能是实体对象、Map 对象或其他类型。

参数说明

  • id:主键ID
  • queryWrapper:实体对象封装操作类 QueryWrapper
  • throwEx:有多个 result 是否抛出异常
  • entity:实体对象
  • mapper:转换函数
// 根据 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);

3.7 list

功能描述: 查询符合条件的记录。

返回值: 查询结果,可能是实体对象、Map 对象或其他类型。

参数说明

  • queryWrapper:实体对象封装操作类 QueryWrapper
  • idList:主键 ID 列表
  • columnMap:表字段 map 对象
  • mapper:转换函数
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)(就是多个key=value条件)
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);

3.8 page

功能描述: 分页查询符合条件的记录。

返回值: 分页查询结果,包含记录列表和总记录数。

参数说明

  • page:翻页对象
  • queryWrapper:实体对象封装操作类 QueryWrapper
// 无条件分页查询
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);

举例:

// 假设要进行无条件的分页查询,每页显示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

3.9 count

功能描述: 查询符合条件的记录总数。

返回值: 符合条件的记录总数。

参数说明

  • queryWrapper:实体对象封装操作类 QueryWrapper
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

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

3.10 lambda方法

在上述方法中,我们条件查询都需要new一个Wrapper来进行设置条件,但是实际上在Service接口中已经帮我们定义了一个lambda方法来直接设置条件了。
用法:

@Override
public List<User> testLambda() {
    return lambdaQuery()
            .eq(User::getName, "张三")
            .ge(User::getAge, 30)
            .list();
}

除了lambdaQuery还有lambdaUpdate,如果我们想调用mapper接口的BaseMapper的方法,我们直接调用baseMapper即可,因为ServiceImpl已经自动注入了BaseMapper

四,Mapper接口

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

只需要在Mapper层基础BaseMapper接口即可。

4.1 insert

功能描述: 插入一条记录。

返回值: int,表示插入操作影响的行数,通常为 1,表示插入成功。

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

4.2 delete

功能描述: 删除符合条件的记录。

返回值: int,表示删除操作影响的行数,通常为 1,表示删除成功。

// 根据 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);

4.3 update

功能描述: 更新符合条件的记录。

返回值: int,表示更新操作影响的行数,通常为 1,表示更新成功。

参数说明

  • entity:实体对象 (set 条件值,可为 null)
  • updateWrapper:实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);

4.4 select

功能描述: 查询符合条件的记录。

返回值: 查询结果,可能是实体对象、Map 对象或其他类型。

参数说明

  • id:主键 ID
  • queryWrapper:实体对象封装操作类(可以为 null)
  • idList:主键 ID 列表(不能为 null 以及 empty)
  • columnMap:表字段 map 对象
  • page:分页查询条件(可以为 RowBounds.DEFAULT)
// 根据 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);
posted @ 2024-07-15 14:18  wdadwa  阅读(454)  评论(0)    收藏  举报