【技术精粹】LambdaQueryWrapper实战指南:MyBatis-Plus从入门到精通(上:入门、基础用法、高级用法)

文章目录

  • [Java MyBatis-Plus LambdaQueryWrapper 深入理解与实战应用](#Java MyBatis-Plus LambdaQueryWrapper 深入理解与实战应用)
    • 前言
    • [第一部分:MyBatis-Plus 入门](#第一部分:MyBatis-Plus 入门)
      • [1.1 MyBatis-Plus 是什么?](#1.1 MyBatis-Plus 是什么?)
      • [1.2 快速上手](#1.2 快速上手)
    • [第二部分:LambdaQueryWrapper 基础](#第二部分:LambdaQueryWrapper 基础)
      • [2.1 LambdaQueryWrapper 概览](#2.1 LambdaQueryWrapper 概览)
      • [2.2 LambdaQueryWrapper 使用入门](#2.2 LambdaQueryWrapper 使用入门)
    • [第三部分:LambdaQueryWrapper 高级用法](#第三部分:LambdaQueryWrapper 高级用法)
      • [3.1 多条件组合查询](#3.1 多条件组合查询)
      • [3.2 排序和分页](#3.2 排序和分页)
      • [3.3 连接查询](#3.3 连接查询)
      • [3.4 动态SQL](#3.4 动态SQL)
      • [3.5 子查询](#3.5 子查询)

Java MyBatis-Plus LambdaQueryWrapper 深入理解与实战应用

【技术精粹】LambdaQueryWrapper实战指南:MyBatis-Plus从入门到精通(下:实战案例、性能优化、进阶)

前言

引言

在Java开发领域中,数据持久层框架是必不可少的一部分,它负责处理应用程序与数据库之间的交互。MyBatis-Plus作为一个流行的增强版MyBatis框架,为开发者提供了许多便捷的功能,其中LambdaQueryWrapper是其核心功能之一。本文旨在深入探讨LambdaQueryWrapper的使用方法及其实战应用,帮助开发者更好地理解和运用这一强大的工具。

MyBatis-Plus 简介

MyBatis-Plus(以下简称MP)是一个基于MyBatis的简化工具,旨在减少程序员编写SQL语句的工作量,同时提供了一套自动化的CRUD操作以及一些高级功能。MP的核心特性包括:

  • 自动映射:无需编写XML映射文件,直接通过注解或配置实现对象关系映射。
  • 通用Mapper:提供了一系列预定义的方法,用于执行基本的增删改查操作。
  • 实体生成器:可以根据数据库表结构自动生成对应的实体类和Mapper接口。
  • 条件构造器:提供了一个灵活的条件构造器,方便构建复杂的查询条件。

LambdaQueryWrapper 的价值

LambdaQueryWrapper是MyBatis-Plus提供的一个强大工具,用于构建复杂的查询条件。相比于传统的QueryWrapper,LambdaQueryWrapper具有以下优点:

  • 更安全:使用lambda表达式代替字符串拼接,避免了SQL注入的风险。
  • 类型安全:由于使用了泛型,编译器可以检查类型错误,提高了代码质量。
  • 可读性好:通过链式调用的方式设置查询条件,使得代码更加简洁易懂。
  • 易于维护:当实体类中的属性名发生变化时,只需要修改实体类即可,不需要修改查询条件代码。

适用读者

本文适合以下类型的读者:

  • 对MyBatis-Plus有一定了解的Java开发者。
  • 希望提高数据访问层开发效率的开发者。
  • 关注代码质量和安全性并希望改进现有项目的开发者。
  • 想要学习LambdaQueryWrapper高级特性的开发者。

接下来的部分我将逐步介绍如何使用LambdaQueryWrapper,并通过实战案例加深理解。

第一部分:MyBatis-Plus 入门

1.1 MyBatis-Plus 是什么?

核心特性

MyBatis-Plus (MP) 是一个 MyBatis 的扩展插件,它简化了日常 CRUD 操作,并提供了许多实用的功能。以下是 MP 的一些核心特性:

  1. 自动映射:通过注解或配置,MP 可以自动完成对象关系映射 (ORM),从而减少了 XML 映射文件的需求。
  2. 通用 Mapper :MP 提供了一组预定义的方法,如 insert(), delete(), update(), select() 等,可以快速实现 CRUD 操作。
  3. 实体生成器:可以根据数据库表结构自动生成对应的实体类和 Mapper 接口。
  4. 条件构造器 :通过 QueryWrapperLambdaQueryWrapper 提供灵活的条件构建机制。
  5. 分页插件:内置的分页功能,支持多种数据库。
  6. 性能分析插件:监控 SQL 执行情况,帮助优化 SQL 语句。

为什么选择 MyBatis-Plus

  • 开发效率:通过通用 Mapper 和自动映射等功能,大大提高了开发效率。
  • 代码质量:利用 Lambda 表达式和类型安全的条件构造器,提高了代码质量和可维护性。
  • 灵活性:虽然提供了大量的自动化功能,但仍然保持了足够的灵活性,允许用户自定义 SQL 语句。
  • 社区支持:MyBatis-Plus 拥有活跃的社区和丰富的文档资源,便于学习和解决问题。

1.2 快速上手

环境搭建

要开始使用 MyBatis-Plus,首先需要搭建一个基本的环境。这里假设您已经熟悉 Java 和 Maven,并且有一个可以运行 Spring Boot 应用的基础项目。

  1. 添加依赖
    在您的 pom.xml 文件中添加 MyBatis-Plus 和相应的数据库驱动依赖。
xml 复制代码
<dependencies>
  <!-- MyBatis Plus -->
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>最新版本号</version>
  </dependency>
  <!-- 数据库驱动 -->
  <dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
  </dependency>
  <!-- Spring Boot Starter JDBC -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
  </dependency>
</dependencies>
  1. 配置数据库连接
    application.propertiesapplication.yml 中配置数据库连接信息。
properties 复制代码
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
  1. 创建实体类
    创建一个简单的实体类,例如 User
java 复制代码
public class User implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private String email;

    // Getters and Setters
}
  1. 创建 Mapper 接口
    创建一个继承自 BaseMapper 的接口,这样就可以直接使用 MyBatis-Plus 提供的方法。
java 复制代码
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserMapper extends BaseMapper<User> {
}
  1. 配置 MyBatis-Plus
    如果使用 Spring Boot,通常不需要额外的配置,因为 mybatis-plus-boot-starter 会自动配置。

HelloWorld 示例

下面是一个简单的示例,展示如何使用 MyBatis-Plus 插入一条记录。

  1. 创建控制器
    创建一个简单的 REST 控制器来处理 HTTP 请求。
java 复制代码
@RestController
public class UserController {

    @Autowired
    private UserMapper userMapper;

    @PostMapping("/save")
    public String save(@RequestBody User user) {
        userMapper.insert(user);
        return "Success";
    }
}
  1. 测试
    使用 Postman 或类似工具发送 POST 请求到 /save,携带 JSON 数据。
json 复制代码
{
    "name": "John Doe",
    "age": 25,
    "email": "john.doe@example.com"
}

基本 CRUD 操作

  • 创建 :使用 insert() 方法插入一条新记录。
  • 读取 :使用 selectById() 方法根据主键查询单条记录;使用 selectList() 查询列表。
  • 更新 :使用 updateById() 更新一条记录;使用 update() 方法配合 UpdateWrapper 更新满足条件的记录。
  • 删除 :使用 deleteById() 删除一条记录;使用 delete() 方法配合 QueryWrapper 删除满足条件的记录。

第二部分:LambdaQueryWrapper 基础

2.1 LambdaQueryWrapper 概览

1. 什么是 LambdaQueryWrapper
LambdaQueryWrapper 是 MyBatis-Plus 中提供的一个用于构建查询条件的工具类。它利用 Java 8 的 Lambda 表达式来构建查询条件,使得查询条件更加简洁、易于理解和维护。

2. 与传统 QueryWrapper 的区别

传统的 QueryWrapper 使用匿名内部类或者方法引用的方式来设置查询条件,这可能会导致代码不够清晰且在编译时无法检查到错误。而 LambdaQueryWrapper 则通过 Lambda 表达式的方式构建条件,这样在编译阶段就可以捕捉到可能的类型错误。

3. LambdaQueryWrapper 的优势

  • 类型安全:由于使用了 Lambda 表达式,所以可以确保在编译阶段就能发现类型错误。
  • 可读性强:代码更加直观,易于理解。
  • 易于维护:Lambda 表达式能够帮助减少代码量,提高可维护性。
  • 方便调试:如果出现错误,调试过程更加简单明了。

2.2 LambdaQueryWrapper 使用入门

1. 创建 LambdaQueryWrapper 实例

首先,你需要创建一个 LambdaQueryWrapper 实例。假设你已经有了一个 User 类,并且已经定义了一个 UserMapper 接口。

java 复制代码
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

public class UserController {

    @Autowired
    private UserMapper userMapper;

    public List<User> getUsers() {
        // 创建 LambdaQueryWrapper 实例
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        
        // 添加查询条件
        queryWrapper.eq(User::getId, 1); // 查询 id 为 1 的用户
        
        // 调用方法执行查询
        List<User> users = userMapper.selectList(queryWrapper);
        
        // 处理结果
        return users;
    }
}

在这个例子中,我们创建了一个 LambdaQueryWrapper 对象并设置了查询条件 eq(User::getId, 1),这意味着我们要查询 id 为 1 的用户。

2. 添加查询条件

你可以向 LambdaQueryWrapper 添加多个查询条件。例如,如果你想查询年龄大于 18 并且名字包含 "John" 的用户,你可以这样写:

java 复制代码
public List<User> getUsers() {
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    
    // 添加多个查询条件
    queryWrapper.gt(User::getAge, 18).like(User::getName, "John");
    
    List<User> users = userMapper.selectList(queryWrapper);
    
    return users;
}

这里使用了 gt() 方法(大于)和 like() 方法(模糊匹配)来添加查询条件。

3. 调用方法

一旦你设置了所有需要的查询条件,你可以调用 UserMapper 接口中对应的方法来执行查询。例如,selectList() 方法用于获取所有符合条件的记录列表。

java 复制代码
List<User> users = userMapper.selectList(queryWrapper);

如果你只需要获取第一条记录,可以使用 selectOne() 方法:

java 复制代码
User user = userMapper.selectOne(queryWrapper);

4. 处理结果

查询完成后,你可以对结果进行进一步处理,比如遍历列表或者对查询结果进行其他业务逻辑操作。

java 复制代码
List<User> users = userMapper.selectList(queryWrapper);

for (User user : users) {
    System.out.println("Found user: " + user.getName());
}

以上就是使用 LambdaQueryWrapper 进行基础查询的步骤。在实际应用中,你还可以结合其他高级功能,如排序、分组、聚合等,以满足更复杂的查询需求。

第三部分:LambdaQueryWrapper 高级用法

3.1 多条件组合查询

1. 等值查询

等值查询是最基本的一种查询方式,可以通过 eq() 方法来实现。例如,查询年龄等于 25 的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getAge, 25);
List<User> users = userMapper.selectList(queryWrapper);

2. 范围查询

范围查询可以通过 between() 方法实现,例如查询年龄在 18 到 30 之间的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.between(User::getAge, 18, 30);
List<User> users = userMapper.selectList(queryWrapper);

3. 模糊查询

模糊查询可以通过 like() 方法实现,例如查询名字包含 "John" 的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.like(User::getName, "John");
List<User> users = userMapper.selectList(queryWrapper);

4. 多条件逻辑组合

多条件逻辑组合可以通过 and()or() 方法来实现,例如查询年龄大于 25 且名字包含 "John" 或者年龄小于 18 的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.gt(User::getAge, 25)
            .and(w -> w.like(User::getName, "John").or().lt(User::getAge, 18));
List<User> users = userMapper.selectList(queryWrapper);

3.2 排序和分页

1. 单字段排序

单字段排序可以通过 orderByAsc()orderByDesc() 方法实现,例如按照年龄升序排列:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByAsc(User::getAge);
List<User> users = userMapper.selectList(queryWrapper);

2. 多字段排序

多字段排序可以通过连续调用 orderByAsc()orderByDesc() 方法实现,例如按照年龄降序排列,如果年龄相同则按名字升序排列:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(User::getAge)
            .orderByAsc(User::getName);
List<User> users = userMapper.selectList(queryWrapper);

3. 分页查询

分页查询可以通过 Page 对象结合 LambdaQueryWrapper 实现,例如查询第一页,每页显示 10 条记录:

java 复制代码
Page<User> page = new Page<>(1, 10);
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(User::getAge);
userMapper.selectPage(page, queryWrapper);

// 获取分页结果
List<User> records = page.getRecords();
long total = page.getTotal();
int currentPage = page.getCurrent();
int pageSize = page.getSize();

3.3 连接查询

1. 内连接

内连接可以通过 innerJoin() 方法实现,例如查询用户与其关联的角色信息:

java 复制代码
LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.innerJoin(User.class, UserRole::getUserId, User::getId);
List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);

2. 左连接

左连接可以通过 leftJoin() 方法实现,例如查询用户及其关联的角色信息,即使某些用户没有角色也会被查询出来:

java 复制代码
LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.leftJoin(User.class, UserRole::getUserId, User::getId);
List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);

3. 右连接

右连接可以通过 rightJoin() 方法实现,例如查询角色及其关联的用户信息,即使某些角色没有用户也会被查询出来:

java 复制代码
LambdaQueryWrapper<UserRole> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.rightJoin(User.class, UserRole::getUserId, User::getId);
List<UserRole> userRoles = userRoleMapper.selectList(queryWrapper);

3.4 动态SQL

1. 动态WHERE子句

动态 WHERE 子句可以通过条件判断来实现,例如只有当 age 不为空时才添加年龄条件:

java 复制代码
Integer age = 25;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
if (age != null) {
    queryWrapper.eq(User::getAge, age);
}
List<User> users = userMapper.selectList(queryWrapper);

2. 动态ORDER BY子句

动态 ORDER BY 子句可以通过条件判断来实现,例如只有当需要排序时才添加排序条件:

java 复制代码
String sortField = "age"; // 假设需要按年龄排序
boolean isAscending = false; // 假设需要按降序排序
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
if ("age".equals(sortField)) {
    if (isAscending) {
        queryWrapper.orderByAsc(User::getAge);
    } else {
        queryWrapper.orderByDesc(User::getAge);
    }
}
List<User> users = userMapper.selectList(queryWrapper);

3. 动态GROUP BY子句

动态 GROUP BY 子句同样可以通过条件判断来实现,例如只有当需要分组时才添加分组条件:

java 复制代码
boolean groupByAge = true; // 假设需要按年龄分组
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
if (groupByAge) {
    queryWrapper.groupBy(User::getAge);
}
List<User> users = userMapper.selectList(queryWrapper);

3.5 子查询

1. 在WHERE子句中使用子查询

可以在 WHERE 子句中使用子查询来过滤数据,例如查询年龄大于平均年龄的用户:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.gt(User::getAge, 
                select(User.class, User::getAge).avg())
            .select(User::getId, User::getName, User::getAge);
List<User> users = userMapper.selectList(queryWrapper);

这里 select(User.class, User::getAge).avg() 代表了一个子查询,计算出所有用户的平均年龄。

2. 在FROM子句中使用子查询

可以在 FROM 子句中使用子查询来构建更复杂的查询逻辑,例如查询某个子查询的结果:

java 复制代码
LambdaQueryWrapper<User> subQueryWrapper = new LambdaQueryWrapper<>();
subQueryWrapper.select(User::getId, User::getName)
               .eq(User::getAge, 25);

LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(User::getId, User::getName, User::getEmail)
            .from(subQueryWrapper);
List<User> users = userMapper.selectList(queryWrapper);

3. 在SELECT子句中使用子查询

在 SELECT 子句中使用子查询可以返回子查询的结果作为查询的一部分,例如查询用户的名字以及他们的平均年龄:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.select(User::getName, 
                    select(User.class, User::getAge).avg().as("average_age"))
            .groupBy(User::getName);
List<User> users = userMapper.selectList(queryWrapper);

这里的 select(User.class, User::getAge).avg().as("average_age") 表示计算平均年龄,并将其命名为 average_age

以上是 LambdaQueryWrapper 的一些高级用法示例,这些技术可以大大提高查询的灵活性和效率。在实际应用中,可以根据具体的业务需求进行组合使用。

【技术精粹】LambdaQueryWrapper实战指南:MyBatis-Plus从入门到精通(下:实战案例、性能优化、进阶)

相关推荐
码里法1 小时前
springmvc用配置类替换xml配置
java·spring·mvc
api茶飘香2 小时前
守护应用边界:通过反射API实现安全的输入输出过滤
java·开发语言·python·安全·django·virtualenv·pygame
杀死一只知更鸟debug2 小时前
策略模式的小记
java·开发语言·策略模式
nice666602 小时前
CSS的基本语法
java·前端·css·visual studio code
sco52822 小时前
【Shiro】Shiro 的学习教程(三)之 SpringBoot 集成 Shiro
spring boot·后端·学习
ever_up9734 小时前
EasyExcel的导入与导出及在实际项目生产场景的一下应用例子
java·开发语言·数据库
小小小小关同学5 小时前
Spring Cloud LoadBalancer
后端·spring·spring cloud
ok!ko5 小时前
设计模式之工厂模式(通俗易懂--代码辅助理解【Java版】)
java·开发语言·设计模式
丷丩6 小时前
一个Java中有用的JacksonUtil类
java·json·工具
爱摄影的程序猿6 小时前
JAVA springboot面试题今日分享
java·spring boot·spring·面试