MyBatis-Plus 条件查询QueryWrapper、聚合函数的使用、Lambda条件查询、定义SQL、分页实现(PaginationInterceptor )、更新和删除

一 、普通查询

// 根据主键id去查询单个结果的。
@Test
public void selectById() {
    User user = userMapper.selectById(1739970502337392641L);
    System.out.println(user);
}

//根据多个主键id批量查询结果的
@Test
public void selectIds() {
    List<Long> list = Arrays.asList(1739970502337392641L, 1739983903621038082L, 1739984905459900417L);
    List<User> userList = userMapper.selectBatchIds(list);
    userList.forEach(System.out::println);
}
// 根据多个条件查询结果的
@Test
public void selectByMap() {
    // map.put("name","小明")
    // map.put("age",30)
    // 相当于 where name ="小明" and age=30
    Map<String, Object> columnMap = new HashMap<>();
    columnMap.put("name", "小刚");
    columnMap.put("age", "18");
    List<User> userList = userMapper.selectByMap(columnMap);
    userList.forEach(System.out::println);
}

条件构造器查询 【重要】

AbstractWrapper 是 MyBatis Plus 中的一个抽象类,用于构建 SQL 查询条件。定义了泛型 T、C 和 Children。其中,T 表示实体类的类型,C 表示查询条件的类型,Children 表示子类的类型,用于支持链式调用。它提供了一系列方法,用于构建 SQL 查询条件,包括设置查询字段、设置查询条件、排序等。

常用实现类包括 QueryWrapper 和 UpdateWrapper。这两个类都是 MyBatis Plus 提供的具体实现,用于构建查询条件和更新条件。
————————————————

@SpringBootTest
public class SelectTests {
    @Autowired
    private UserMapper userMapper;

    /**
     * 1.名字中包含刘且年龄大于20
     * name like '%刘%' and age>20
     */
    @Test
    public void selectByWrapper() {
        // 创建queryWrapper的两种方式
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//        QueryWrapper<User> queryWrapper1 = Wrappers.<User>query();
        queryWrapper.like("name", "刘").gt("age", 20);
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }

    /**
     * 2.名字中包含刘且年龄大于等于20且小于30并且email不为空
     * name like ‘%刘’ and age between 20 and 30 and email is not null
     */
    @Test
    public void selectByWrapper2() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "刘").between("age", 20, 30).isNull("email");
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }

    /**
     * 3.名字中包含刘或年龄大于等于20,按照年龄降序排序,年龄相同按照id升序排列
     * name like ‘%刘’ and age between 20 and 30 and email is not null
     */
    @Test
    public void selectByWrapper3() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "刘").or().ge("age",20)
                .orderByDesc("age")
                .orderByAsc("user_id");

        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    /**
     * 4.创建日期为2023年12月17日并且直属上级为王姓
     * date_format(create_time,'%Y-%m-$d') and manager_id in(select id from user where name like '王%'
     */
    @Test
    public void selectByWrapper4() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.apply("date_format(create_time,'%Y-%m-%d')={0}", "2023-12-27") //  使用占位符避免sql注入的风险
                .inSql("manager_id","select user_id from mp_user where name like '王%'");
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    /**
     * 5.名字为刘姓且年龄小于30或者邮箱不为空
     * name like '王%' and (age<20 or email is not null)
     */
    @Test
    public void selectByWrapper5() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("name", "刘")
                .and(wq -> wq.lt("age", 30).or().isNotNull("email"));
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    /**
     * 6.名字为刘姓或者(年龄小于30且大于20并且邮箱不为空)
     * name like '刘%' or (age<30 and age>20 and email is not null)
     */
    @Test
    public void selectByWrapper6() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("name", "刘")
                .or(wq -> wq.lt("age", 30).gt("age", 20)
                        .isNotNull("email"));

        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    /**
     * 7.(年龄小于30且邮箱不为空)并且名字为刘姓
     *  (age<30 or email is not null) and name like '刘%'
     */
    @Test
    public void selectByWrapper7() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.nested(wq -> wq.lt("age", 30)
                        .or().isNotNull("email"))
                .likeRight("name", "刘");
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    /**
     * 8. 年龄为 21 25 33
     *  age in(21,25,33)
     */
    @Test
    public void selectByWrapper8() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("age", 21, 25, 33);
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
    /**
     * 9. 只返回满足条件的其中一条语句即可
     *  limit 1
     */
    @Test
    public void selectByWrapper9() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("age", 21, 25, 33).last("limit 1"); // last() 有sql注入的风险,谨慎使用
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }
}

select 不列出全部字段

 /**
   * 10.名字中包含刘且年龄小于30(需求1加强版)
   */
  @Test
  public void selectByWrapper() {
      QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//        queryWrapper.select("user_id","name","age").like("name", "刘").lt("age", 30); // 包含字段
      queryWrapper.like("name", "刘").lt("age", 30)
              .select(User.class, info ->
                      !info.getColumn().equals("create_time") && !info.getColumn().equals("manager_id"));// 排除字段
      List<User> list = userMapper.selectList(queryWrapper);
      list.forEach(System.out::println);
  }

condition作用

根据判断决定查询条件是否加到sql语句里面

@Test
    public void testCondition() {
        String name = "东";
        String email = "";
        condition(name, email);
    }
    private void condition(String name, String email) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//        if (StringUtils.isNotEmpty(name)) {
//            queryWrapper.like("name", name);
//        }
//        if (StringUtils.isNotEmpty(email)) {
//            queryWrapper.like("email", email);
//        }
        queryWrapper.like(StringUtils.isNotEmpty(name), "name", name)
                .like(StringUtils.isNotEmpty(email), "email", email);
        List<User> list = userMapper.selectList(queryWrapper);
        list.forEach(System.out::println);
    }

实体作为条件构造器构造方法的参数

@Test
public void selectByWrapperEntity() {
    User user = new User();
    user.setRealName("小刚");
    user.setAge(18);
    QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}
运行结果的sql语句:SELECT * FROM mp_user WHERE **name=? AND age=?**
会把set注入的属性和值映射到where条件中

通过SqlCondition 更改查询条件

用法
@TableField(condition = SqlCondition.LIKE)
private String name;
@TableField(condition = "%s&lt;#{%s}") //根据定义的常量,自己也可以参考并更改
private Integer age;
运行结果:SELECT * FROM mp_user WHERE **name LIKE CONCAT('%',?,'%')** AND AND age<?

allEq

**allEq**是一个查询条件配置方法,用于构建查询条件。它可以根据传入的条件参数,生成一个包含所有等值条件的查询条件对象。

@Test
public void selectByWrapperAllEq() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    Map<String, Object> params = new HashMap<>();
    params.put("name", "小明");
    params.put("age", null);
    **queryWrapper.allEq(params,false)**; // false代表忽略值为null的字段,即不参与where条件
    List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}

其他条件构造器

**selectMaps 返回**

@Test
    public void selectByWrapperMaps() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("user_id","name").like("name", "刘").lt("age", 30);
//        List<User> list = userMapper.selectList(queryWrapper);// 返回值为实体类的话,没设置的值还是会返回,只不过值为null
        List<Map<String, Object>> userList = userMapper.selectMaps(queryWrapper);// 只返回限定的字段
        userList.forEach(System.out::println);
    }

    /** 示例
     * 11.按照直属上级分组,查询每组的平均年龄、最大年龄、最小年龄,并且至取年龄总和为500的组
     * select avg(age)avg_age,min(age) min_age,max(age) max_age from user group by manager_id having sum(age)<500
     */
    @Test
    public void selectByWrapperMaps2() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("avg(age) avg_age", "min(age) min_age", "max(age) max_age")
                .groupBy("manager_id").having("sum(age)<{0}", 500);
        List<Map<String, Object>> userList = userMapper.selectMaps(queryWrapper);
        userList.forEach(System.out::println);
    }

lambda条件构造器

@Test
public void selectLambda() {
    //创建lambda条件构造器的三种方式
    LambdaQueryWrapper<User> lambda = new LambdaQueryWrapper<>();
    LambdaQueryWrapper<User> lambda2 = new QueryWrapper<User>().lambda();
    LambdaQueryWrapper<User> lambda3= Wrappers.<User>lambdaQuery();

    lambda3.like(User::getName, "刘")
            .lt(User::getAge, 30); // where name like '%雨%' and age<30
    List<User> userList = userMapper.selectList(lambda3);
    userList.forEach(System.out::println);
}
/**
 * 5.名字为刘姓且(年龄小于30或邮箱不为空)
 * name like '刘%' and (age<30 or email is not null)
 */
@Test
public void selectLambda2() {
    LambdaQueryWrapper<User> lambda= Wrappers.<User>lambdaQuery();
    lambda.like(User::getName, "刘")
            .and(wq -> wq.lt(User::getAge, 20)
                    .or().isNotNull(User::getEmail));
    List<User> userList = userMapper.selectList(lambda);
    userList.forEach(System.out::println);
}
// 链式调用多个条件 LambdaQueryChainWrapper
@Test
public void selectLambda3() {
    List<User> userList = new LambdaQueryChainWrapper<>(userMapper)
            .like(User::getName, "刘").ge(User::getAge, 20).list();
    userList.forEach(System.out::println);
}
自定义SQL

自定义mapper文件是为了应对一些更复杂的查询场景,首先先配置映射路径

mybatis-plus:
  mapper-locations: com/mp/dao/xml/*

由于这里的mapper文件放在java文件夹中,所以要在pom.xml里进行配置

<build>
  <resources>
      <resource>
          <!-- xml放在java目录下-->
          <directory>src/main/java</directory>
          <includes>
              <include>**/*.xml</include>
          </includes>
      </resource>
      <!--指定资源的位置(xml放在resources下,可以不用指定)-->
      <resource>
          <directory>src/main/java</directory>
      </resource>
  </resources>
</build>

mapper

public interface UserMapper extends BaseMapper<User> {
    List<User> selectAll(@Param(Constants.WRAPPER) Wrapper<User> wrapper);
}
<?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.mp.dao.UserMapper">
    <select id="selectAll" resultType="com.mp.entity.User">
        select * FROM `mp_user` ${ew.customSqlSegment}
    </select>
</mapper>
@Test
    public void selectMy() {
        LambdaQueryWrapper<User> lambda= Wrappers.<User>lambdaQuery();
        lambda.likeRight(User::getName,"刘")
                .and(lqw->lqw.lt(User::getAge,30)
                        .or().isNotNull(User::getEmail));
        List<User> userList = userMapper.selectAll(lambda);
        userList.forEach(System.out::println);
    }

分页
在MyBatis Plus中,物理分页和内存分页是两种不同的分页方式。

**物理分页【推荐】是在数据库层面进行分页操作,通过SQL语句的LIMIT和OFFSET**关键字来实现。这种分页方式直接在数据库中进行数据的截取和返回,因此适用于大数据量的分页查询。

**内存分页【了解】**是在应用程序内存中进行分页操作,即先将所有数据查询出来,然后在内存中进行分页处理。这种分页方式适用于数据量较小的情况,因为需要将所有数据加载到内存中,可能会导致内存占用过高。

配置插件

@Configuration
public class MybatisPlusConfig {
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

分页实现

@Test
public void selectPage() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.ge("age", 30);
    Page<User> page = new Page<User>(1, 2,false);// fasle指的是不查询总记录数,提高性能
//        IPage<User> iPage = userMapper.selectPage(page, queryWrapper);
//        List<User> userList = iPage.getRecords();
		// selectMapsPage 
    IPage<Map<String, Object>> iPage = userMapper.selectMapsPage(page, queryWrapper);
    System.out.println("总页数 = " + iPage.getPages());
    System.out.println("总记录数 = " + iPage.getTotal());
    List<Map<String, Object>> userList = iPage.getRecords();
    userList.forEach(System.out::println);
}

自定义分页

UserMapper

IPage<User> selectUserPage(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper);
}

UserMapper.xml

<select id="selectUserPage" resultType="com.mp.entity.User">
    select * from mp_user ${ew.customSqlSegment}
</select>
@Test
public void selectMyPage() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.ge("age", 30);
    Page<User> page = new Page<User>(1, 2);
    IPage<User> iPage = userMapper.selectUserPage(page, queryWrapper);
    System.out.println("总页数 = " + iPage.getPages());
    System.out.println("总记录数 = " + iPage.getTotal());
    List<User> userList = iPage.getRecords();
    userList.forEach(System.out::println);
}
Update,更新方法详解
@Test
public void updateById() {
    User user = new User();
    user.setUserId(3L);
    user.setAge(28);
    user.setEmail("xiao@163.com");
    // 传入实体对象作为参数,自动根据id字段定位对应的记录,根据其他set的值进行更新
    int rows = userMapper.updateById(user);
    System.out.println("rows = " + rows);
}
/**
 * 条件构造器更新
 */
@Test
public void updateByWrapper() {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.eq("name", "小刚").eq("age", 18); // where条件
    // set更新条件
    User user = new User();
    user.setAge(28);
    user.setEmail("xiao@163.com");
    // 传入实体对象作为参数,自动根据id字段定位对应的记录,根据其他set的值进行更新
    int rows = userMapper.update(user, updateWrapper);
    System.out.println("rows = " + rows);
}
/**
 * 快速更新少量字段
 */
@Test
public void updateByWrapper2() {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.eq("name", "李刚").eq("age", 29).set("age", 30);
    int rows = userMapper.update(null,updateWrapper);
    System.out.println("rows = " + rows);
}
/**
 * lambda表达式
 */
@Test
public void updateByWrapper3() {
    LambdaUpdateWrapper<User> lambdaUpdate = Wrappers.lambdaUpdate();
    lambdaUpdate.eq(User::getName, "小刚").eq(User::getAge, 28).set(User::getAge, 31);
    int rows = userMapper.update(null,lambdaUpdate);
    System.out.println("rows = " + rows);
}

/**
 * lambda表达式链式调用
 */
@Test
public void updateByWrapper4() {
    boolean update = new LambdaUpdateChainWrapper<User>(userMapper)
            .eq(User::getName, "小刚").eq(User::getAge, 31).set(User::getAge,28).update();
    System.out.println("update = " + update);
}
Delete 删除
@Test
public void deleteById() {
    int rows = userMapper.deleteById(1739970502337392641L);
    System.out.println("rows = " + rows);
}

@Test
public void deleteByMap() {
    Map<String,Object> map = new HashMap<>();
    map.put("name", "小刚");
    map.put("age", "25");
    // DELETE FROM mp_user WHERE name = ? AND age = ?
    int rows = userMapper.deleteByMap(map);
    System.out.println("rows = " + rows);
}

@Test
public void deleteBatchIds() {
    int rows = userMapper.deleteBatchIds(Arrays.asList(121111123010L, 126372731123L, 127381787813L));
    // 相当于 where id in(?,?,?)
    System.out.println("rows = " + rows);
}

@Test
public void deleteByWrapper() {
    LambdaQueryWrapper<User> lambdaQuery = Wrappers.lambdaQuery();
    lambdaQuery.eq(User::getAge, 28)
            .or().gt(User::getAge, 41);
    int rows = userMapper.delete(lambdaQuery);
    System.out.println("rows = " + rows);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值