MyBatisPlus的基本使用之QueryWrapper

本文详细介绍了MyBatis-Plus中的QueryWrapper和LambdaQueryChainWrapper查询封装类,比较了两者在设置查询条件和使用方式上的异同,并通过代码示例展示了如何进行基本查询、复杂查询、分页查询以及乐观锁的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QueryWrapper是MyBatis-Plus中的一个查询封装类,用于构建带有条件的查询语句。

1. QueryWrapper

使用普通的方式来设置查询条件,而不是使用Lambda表达式。

  • 一系列方法设置查询条件。手动指定数据库表的列名作为方法的参数
    • select 设置查询的字段
    • eq、ne、gt、ge、lt、le 设置等于、不等于、大于、大于等于、小于、小于等于。
    • orderBy 排序方式
    • last 自定义SQL语句

2.区别

  • LambdaQueryChainWrapper使用Lambda表达式来设置查询条件,更加直观和类型安全
  • -而QueryWrapper使用普通方式来设置查询条件,更加灵活和通用

3.代码示例

package com.example.demo.mybatisplus.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.zmybatisplus.entity.User;
import com.example.demo.zmybatisplus.mapper.UserMapper;
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.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SpringBootTest
public class UserTest {

    @Autowired
    private UserMapper userMapper;

    //----------------------------------  查询 ---------------------------------------------------

    //简单查询
    @Test
    public void testSelect() {
        //所有
        List<User> userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
        //多个
        List<User> userList2 = userMapper.selectBatchIds(Arrays.asList(1L,2L,3L));
        userList2.forEach(System.out::println);
        //单个
        User user3 = userMapper.selectById(1L);
        System.out.println(user3);
    }

    //等值条件查询,-- HashMap
    @Test
    public void testSelectByMap() {
        HashMap<String, Object> map = new HashMap<>();
        //定义查询条件
        map.put("name", "小垃圾"); //where k = v
        map.put("age",0);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }

    //Wrapper查询---1.数字的比较 2.字符串的模糊查询
    @Test
    public void testSelectByWrapper() {

        //链式调用构造查询条件
       QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.isNotNull("name")
                .like("email","john")
                .le("age",26)
                .lt("version",2)
                .orderByAsc("id","age");

        //选择API执行query
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);

        //        eq相等   ne不相等,   gt大于,    lt小于         ge大于等于       le 小于等于
        //        equal/ not equal/ greater than/ less than/ less than or equal/ great than or equal/

        //模糊查询 like  notLike  likeLeft(%x)  likeRight   notLikeLeft  notLikeRight

    }


    //Wrapper查询---1. 查询区间内的记录  between
    //              2.集合  in (in  notIn)(inSql   notInSql)
    @Test
    void test2SelectByWrapper(){
        //查询区间内的记录  between
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name").between("age",20,30);
        Long count = userMapper.selectCount(wrapper);
        System.out.println("count = " + count);

        //集合IN : in  notIn
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.in("id",Arrays.asList(1L,2L,3L,4L));
        Long c=userMapper.selectCount(queryWrapper);
        System.out.println("count="+c);

        // 集合  IN ( sql语句 )  :  inSql   notInSql
        //例: inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)
        //例: inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)
        QueryWrapper<User> queryWrapper2=new QueryWrapper<>();
        //queryWrapper2.inSql("id","1,2,3,4");//两种写法
        queryWrapper2.inSql("id","select id from user where id<=4");
        Long c2=userMapper.selectCount(queryWrapper);
        System.out.println("count="+c2);

    }

    //Wrapper查询---分组查询 groupBy  having
    @Test
    public void testGroupByByWrapper(){
        QueryWrapper<User> wrapper=new QueryWrapper<>();
        wrapper.select("version","sum(age) as num")
                .groupBy("version")
                .having("sum(age)>0")
                .orderByDesc("num");

        //使用Map获取返回结果
        List<Map<String,Object>> list=userMapper.selectMaps(wrapper);

        list.forEach(System.out::println);
    }


    //Wrapper更新---
    @Test
    public void testUpdateWrapper() {

        //修改--所有的记录

//        //方式1
//        UpdateWrapper<User> updateWrapper=new UpdateWrapper<>();
//        updateWrapper.set("name","updateName").set("email",null);
//        userMapper.update(updateWrapper);
//
//        //方式2
//        String sql = "name = 'updateName1', email = null ";
//        int affectedRows = userMapper.update(new UpdateWrapper<User>().setSql(sql));
//        System.out.println("Affected rows: " + affectedRows);

        //修改 -- id=1的记录  UpdateWrapper拥有 QueryWrapper一样的条件方法
        UpdateWrapper<User> updateWrapper2 = new UpdateWrapper<>();
        updateWrapper2.set("name", "updateName111").set("email", "人文氛围v给xxx@123.cpm").eq("id", 1);
        userMapper.update(null, updateWrapper2);


    }

    //分页查询
    @Test
    public void testPage() {
        Page<User> page = new Page<>(2,5); //开启拦截器后,会注册一个page对象  当前页,每页条数
        //方法源码:   <P extends IPage<T>> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
        userMapper.selectPage(page,null); //分页查询
        page.getRecords().forEach(System.out::println); //获取分页后的数据 打印
        System.out.println(page.getTotal()); //获取记录总数
    }

    //链式查询:  使用 Lambda 表达式的链式查询对象
    /*
     public List<User> getUserListByQueryWrapper() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("age", 25)
                .like("name", "John")
                .orderByDesc("create_time");

        List<User> userList = userMapper.selectList(queryWrapper);
        return userList;
    }

    public List<User> getUserListByLambdaQueryChainWrapper() {
        LambdaQueryChainWrapper<User> lambdaQueryWrapper = new LambdaQueryChainWrapper<>(userMapper);
        lambdaQueryWrapper.eq(User::getAge, 25)
                .like(User::getName, "John")
                .orderByDesc(User::getCreateTime);

        List<User> userList = lambdaQueryWrapper.list();
        return userList;
    }

    public List<User> getUserListByLambdaQueryChainWrapperWithPage(int pageNum, int pageSize) {
        LambdaQueryChainWrapper<User> lambdaQueryWrapper = new LambdaQueryChainWrapper<>(userMapper);
        lambdaQueryWrapper.eq(User::getAge, 25)
                .like(User::getName, "John")
                .orderByDesc(User::getCreateTime)
                .page(new Page<>(pageNum, pageSize));

        List<User> userList = lambdaQueryWrapper.list();
        return userList;
    }
     */




    //---------------------------增删改-查-------------------------------------------
    //加入了逻辑删除之后,查询会自动增加 delfalg=0;
    @Test
    public void testSelectById() {
        System.out.println("----- selectById method test -----");
        User user = userMapper.selectById(1L);
        Assertions.assertNotNull(user);
        System.out.println(user);

    }

    @Test
    public void testInsert() {
        System.out.println("----- insert method test -----");
        User user = new User();
        user.setName("John 雪花算法");
        user.setAge(25);
        user.setEmail("john.doe@example.com");
        int result = userMapper.insert(user);
        Assertions.assertEquals(1, result);
        System.out.println("Inserted user ID: " + user.getId());
    }

    @Test
    public void testUpdateById() {
        System.out.println("----- updateById method test -----");
        User user = new User();
        user.setId(1L);
        user.setAge(0);//update注解优先自定义设值
        int result = userMapper.updateById(user);
        Assertions.assertEquals(1, result);
    }

    //配置了全局逻辑删除 delfalg=0;
    @Test
    public void testDeleteById() {
        System.out.println("----- deleteById method test -----");
        int result = userMapper.deleteById(5L);
        Assertions.assertEquals(1, result);
        int r=userMapper.deleteBatchIds(Arrays.asList(1L,2L,3L));
    }


    //-------------------------- 乐观锁     ---------------------------------
    /*
    乐观锁(OptimisticLockerInnerInterceptor)机制:
       当要更新一条记录的时候,希望这条记录没有被别人更新

乐观锁实现方式:
取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
     */
    @Test//乐观锁测试
    public void testOptimisticLocker(){
        //1、查询用户信息
        User user = userMapper.selectById(1L);
        //2、修改用户信息
        user.setEmail("123@qq.com");
        user.setName("小垃圾");
        //3、更新操作
        userMapper.updateById(user);  //WHERE id=? AND version=?
    }

    @Test
    public void testOptimisticLocker2(){
        //模拟多线程
        User user = userMapper.selectById(2L);
        user.setEmail("111jdw@qq.com");
        user.setName("帅小伙111");//我们在这里对线程1修改值

        //线程2插队
        User user2 = userMapper.selectById(2L);
        user2.setEmail("222jdw@qq.com");
        user2.setName("帅小伙222");
        userMapper.updateById(user2); //线程2抢先提交

        userMapper.updateById(user);//线程1失败,乐观锁在这种情况下防止了脏数据存在,没有乐观锁就会有覆盖掉线程2的操作
    }






}
<think>好的,我现在需要帮用户了解如何使用MyBatisPlusQueryWrapper进行查询,包括示例教程和最佳实践。用户已经提供了一些引用资料,我需要结合这些内容来组织回答。 首先,我应该从基础开始,介绍QueryWrapper是什么,然后给出基本查询的示例。比如查询所有用户,或者根据某个字段进行过滤。这部分需要代码示例,用Java和MyBatisPlus的语法。 接下来,用户可能需要知道如何进行条件组合,比如and和or的使用。比如查询年龄大于18且姓名包含“张”的用户,或者状态为启用或未删除的情况。这时候需要用QueryWrapper的链式调用方法,如.eq(), .like(), .or()等。 然后,排序和分页也是常见的需求。需要展示如何使用orderByAsc、orderByDesc,以及结合Page对象进行分页查询。这部分要注意分页配置是否启用,可能需要添加分页拦截器。 子查询和嵌套查询可能稍微复杂一些,用户可能想知道如何处理这种情况。比如查询部门ID在某个子查询结果中的用户。这里可以使用.inSql()方法,传入子查询的SQL语句。 关联到用户提供的引用内容,特别是引用[1]提到安全高效地使用Wrapper,引用[3]强调LambdaQueryWrapper的类型安全。可能需要在最佳实践部分提到使用Lambda表达式的好处,比如防止字段名错误,提高可维护性。 最佳实践部分需要包括几个要点:使用Lambda方式避免硬编码,避免SQL注入,合理使用链式调用,以及组合复杂条件时的代码可读性。每个点都要结合引用内容,比如引用[1]的安全实践,引用[3]的类型安全。 然后生成相关问题,可能需要考虑用户进一步可能想知道的内容,比如和LambdaQueryWrapper的区别,如何做多表查询(这里可以关联引用[2]提到的MyBatis-Plus Join工具),以及性能优化和事务管理的问题。 需要确保所有代码示例正确,符合MyBatisPlus的语法,并且遵循用户给出的格式要求,比如行内公式用$...$,独立公式用$$...$$,但可能在这个问题中数学公式不多,主要关注代码格式。同时回答使用中文,结构清晰,分步骤说明。 最后检查引用标记是否正确添加,比如在提到安全最佳实践时引用[^1],提到多表查询时引用[^2],提到LambdaQueryWrapper时引用[^3]。确保每个引用与内容对应,并且自然衔接。</think>以下是如何使用MyBatis-Plus的QueryWrapper进行查询的详细说明,包含示例教程和最佳实践: ### 一、QueryWrapper基础用法 1. **基础查询** 查询所有`age > 18`的用户: ```java QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.gt("age", 18); List<User> userList = userMapper.selectList(queryWrapper); ``` 2. **条件组合** 查询`age > 18`且`name`包含"张"的用户: ```java queryWrapper.gt("age", 18) .like("name", "张"); ``` 3. **OR条件** 查询状态为`启用(1)` **或** `未删除(0)`的用户: ```java queryWrapper.eq("status", 1) .or() .eq("is_deleted", 0); ``` ### 二、进阶查询示例 1. **排序与分页** ```java // 按创建时间倒序 queryWrapper.orderByDesc("create_time"); // 分页查询(需配置分页插件) Page<User> page = new Page<>(1, 10); IPage<User> userPage = userMapper.selectPage(page, queryWrapper); ``` 2. **子查询** 查询部门ID存在于子查询结果的用户: ```java queryWrapper.inSql("dept_id", "SELECT id FROM dept WHERE status = 1"); ``` ### 三、最佳实践 1. **使用Lambda表达式** 推荐改用`LambdaQueryWrapper`避免字段硬编码: ```java LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>(); lambdaWrapper.gt(User::getAge, 18) .like(User::getName, "张"); ``` 2. **防SQL注入** - 避免直接拼接用户输入: ```java // 错误方式 wrapper.apply("date_format(create_time,'%Y') = " + inputYear); // 正确方式 wrapper.apply("date_format(create_time,'%Y') = {0}", inputYear); ``` - 使用预编译参数可有效防止注入风险 3. **链式调用优化** 复杂条件建议分步编写: ```java wrapper.gt(age > 0, "age", age) // 动态条件 .nested(i -> i.like("name", "张").or().like("email", "张")) .select("id", "name"); // 字段过滤 ``` ### 四、关联查询方案 对于多表查询需求,可结合MyBatis-Plus Join工具[^2]: ```java MPJLambdaWrapper<User> joinWrapper = new MPJLambdaWrapper<>(); joinWrapper.selectAll(User.class) .leftJoin(Dept.class, Dept::getId, User::getDeptId) .eq(Dept::getStatus, 1); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值