MyBatis Plus实战(二)条件查询

条件查询

抽象类Wrapper是所有条件构造器的父类,我们使用它的子类QueryWrapper完成条件构造。

QueryWrapper封装的方法

setSqlSelect 设置 SELECT 查询字段
where WHERE 语句,拼接 + WHERE 条件
and AND 语句,拼接 + AND 字段=值
andNew AND 语句,拼接 + AND (字段=值)
or OR 语句,拼接 + OR 字段=值
orNew OR 语句,拼接 + OR (字段=值)
eq 等于=
allEq 基于 map 内容等于=
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<=
like         模糊查询 LIKE
notLike 模糊查询 NOT LIKE
in IN  查询
notIn NOT IN 查询
isNull NULL 值查询
isNotNull         IS NOT NULL
groupBy 分组 GROUP BY
having HAVING 关键词
orderBy 排序 ORDER BY
orderAsc         ASC 排序 ORDER BY
orderDesc DESC 排序 ORDER BY
exists EXISTS 条件语句
notExists         NOT EXISTS 条件语句
between BETWEEN 条件语句
notBetween NOT BETWEEN 条件语句
addFilter         自由拼接 SQL
last         拼接在最后,例如:last("LIMIT 1")

如果点进每一个方法查看源码发现,所有方法都调用了一个同名的方法,这个方法的第一个参数为 boolean condition,它表示该条件是否加入最后生成的sql中,如果设为false,则没有改条件。使用场景:多条件查询时,根据是否传递该属性值来决定SQL生成。

//like的源码
    default Children like(R column, Object val) {
        return this.like(true, column, val);
    }

查询全部字段

查询用户名中有 “m”的数据

	@Test
    public void selectCondition1() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name", "m");
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }

查询姓名有“m”,年龄在0-20岁之间,上级id不为null的数据

	@Test
    public void selectCondition2() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("user_name", "m").between("age", 0, 20).isNotNull("manager_id");
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }

姓氏为"m",或者年龄大于7岁,按照年龄降序排序,年龄相同的按照id升序

	@Test
    public void selectCondition3() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        /*
         * like: '%值%'
         * likeLeft: '%值'
         * lifeRight: '值%'
         */
        queryWrapper.likeRight("user_name", "m").or().ge("age", 7)
                .orderBy(true, false, "age")
                .orderBy(true, true, "id");
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }

查询姓氏为"m",并且年龄小于40且大于3

	@Test
    public void selectCondition4() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("user_name", "m").and(qw -> qw.lt("age", 30).gt("age", 3));
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }

查询部分字段

只需要id,name字段

	@Test
    public void selectCondition5() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "user_name").like("user_name", "m").lt("age", 30);
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }

排除email,age字段

    @Test
    public void selectCondition6() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.select(User.class, user -> !user.getColumn().equals("age") && !user.getColumn().equals("email"));
        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }

对象实例作构造方法参数

上面使用的条件构造器中,采用的都是无参构造方法,MP允许我们传递实体对象给条件构造器,其中实体对象不为null的属性将作为where条件,默认 = 比较。实例生成的where条件与各个Api生成的where条件没有任何关联行为,都会出现在sql的where中。

	@Test
    public void selectCondition7() {
        User user = new User();
        user.setName("mike");
        user.setAge(10)
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);

        List<User> userList = userMapper.selectList(queryWrapper);
        userList.forEach(System.out::println);
    }
/*
未使用其他方法:
生成Sql: where user_name = ? AND age = ?
加上条件queryWrapper.likeRight("user_name","m").gt("age",10);
生成Sql:where user_name = ? AND age = ? AND (user_name LIKE ? AND age > ?)
*/

传入对象实例默认构造的where条件是 等值 = 比较,某些场景下不符合我们的要求,此时可以使用之前提到过的@TableFiled注解,在name上标注@TableFiled(condition = SqlCondition.LIKE),来改变默认条件。改变默认条件后,生成的SQL:WHERE user_name LIKE CONCAT('%' , ? , %") AND age = ?

/**
 * SQL 比较条件常量定义类
 */
public class SqlCondition {
    /**
     * 等于
     */
    public static final String EQUAL = "%s=#{%s}";
    /**
     * 不等于
     */
    public static final String NOT_EQUAL = "%s&lt;&gt;#{%s}";
    /**
     * % 两边 %
     */
    public static final String LIKE = "%s LIKE CONCAT('%%',#{%s},'%%')";
    /**
     * % 左
     */
    public static final String LIKE_LEFT = "%s LIKE CONCAT('%%',#{%s})";
    /**
     * 右 %
     */
    public static final String LIKE_RIGHT = "%s LIKE CONCAT(#{%s},'%%')";
}

这里还可以自定义构造条件,不同场景不同方式,不再赘述。

更多查询方法

SelectMaps

    @Test
    public void selectCondition8() {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
        System.out.println(users);
    }

使用SelectMaps看似跟SelectList没有区别,看一下打印结果:

[{create_time=2021-07-20T17:13:31, manager_id=2, name=mike, id=1, age=10, email=mikemike@qq.com}, 
{create_time=2021-07-20T17:41:14, name=tom, id=2, age=24, email=tomtom@qq.com},
{create_time=2021-07-19T14:15:50, manager_id=1, name=ez, id=3, age=20, email=ezez@qq.com}]

SelectMaps帮我们剔去了值为null的字段,当大量字段是null时,为了方便看数据,SelectMaps就出场了。

@Test
public void selectCondition8() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("id","user_name","email");
    List<Map<String, Object>> users = userMapper.selectMaps(queryWrapper);
    System.out.println(users);
}

打印结果:
[{user_name=mike, id=1, email=mikemike@qq.com}, {user_name=tom, id=2, email=tomtom@qq.com}, {user_name=ez, id=3, email=ezez@qq.com}]

SelectObjs
根据Wrapper条件,查询全部记录,但只返回第一个字段的值。

@Test
public void selectCondition9() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    List<Object> objects = userMapper.selectObjs(queryWrapper);
    System.out.println(objects);
}

第一个字段是id,所以打印结果:[1, 2, 3]

SelectCount

根据QuerWrapper条件查询总数

@Test
public void selectCondition10() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.ge("age",10);
    Integer count = userMapper.selectCount(queryWrapper);
    System.out.println(count);
}
   /**
     * 使用selectCount方法不能知道查询的列名
     * 生成SQL:SELECT COUNT( 1 ) FROM user WHERE (age >= ?) 
     */

打印结果:3 (有3条年龄大于等于10的数据)

SelectOne

根据queryWrapper条件返回一条记录,且只能返回一条或Null,否则报错。

@Test
public void selectCondition11() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name", "mike");
    User user = userMapper.selectOne(queryWrapper);
    System.out.println(user);
}

打印结果:

User(id=1, name=mike, age=10, email=mikemike@qq.com, managerId=2, createTime=2021-07-20T17:13:31, updateTime=null, version=null, deleteId=null)

lambda条件构造器

除了上面的QueryWrapper条件构造器,MP还提供了Lambda条件构造器,它能防止我们写错字段名称。

三种方式创建Lambda条件构造器:

LambdaQueryWrapper<User> lambdaWrapper = new QueryWrapper<User>().lambda();
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>(); 
LambdaQueryWrapper<User> lambdaWrapper = Wrappers.lambdaQuery();

测试:

@Test
public void lamdaTest() {

    LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();
    lambdaQueryWrapper.like(User::getName, "tom").ge(User::getAge, 10);
    List<User> userList = userMapper.selectList(lambdaQueryWrapper);

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

打印结果:

User(id=2, name=tom, age=24, email=tomtom@qq.com, managerId=null, createTime=2021-07-20T17:41:14, updateTime=null, version=null, deleteId=null)

LambdaQueryChainWrapper

允许我们链式构造where条件和调用查询方法。

    @Test
    public void lambdaTest2() {
        List<User> userList = new LambdaQueryChainWrapper<User>(userMapper)
                .like(User::getName, "mike")
                .ge(User::getAge, 10).list();
        userList.forEach(System.out::println);
    }

打印结果:

User(id=1, name=mike, age=10, email=mikemike@qq.com, managerId=2, createTime=2021-07-20T17:13:31, updateTime=null, version=null, deleteId=null)

查看LambdaQueryChainWrapper源码,实际上内部新创建了LambdaQueryWrapper,和分开写条件并没什么区别。

LambdaQueryChainWrapper 实现了ChainQuery接口,此接口提供了list,one等方法。

posted @ 2021-07-21 17:59  Leejk  阅读(2374)  评论(0编辑  收藏  举报