在写SQL where条件的时候我们经常使用 =、!=、>、>=、 <、<=、in、like、between and、not、is null 等来构造条件,在MyBatis-Plus中也可以通过方法来构造这些where条件,在MyBatis-Plus中使用以下类来构造where条件:
QueryWrapper(LambdaQueryWrapper)UpdateWrapper(LambdaUpdateWrapper) QueryWrapper<User> queryWrapper new QueryWrapper<>(); QueryWrapper<User> queryWrapper new QueryWrapper<>(entity); QueryWrapper<User> query = Wrappers.query(); // lambda风格 LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<User> lambda = new QueryWrapper<User>().lambda(); // 构造update语句where条件 UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(); UpdateWrapper<User> update = Wrappers.update(); LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();用于查询指定字段,可以使用谓词来包含或者排除某些字段。
// 查询指定列 select(String... sqlSelect) // 通过谓词来过滤列(排除或者包含) select(Predicate<TableFieldInfo> predicate) select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) // SELECT id,age,username FROM tbl_user order by id asc, age desc LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .select(User::getId, User::getAge, User::getUsername); // ELECT id,username,name,...,update_time FROM tbl_user LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .select(User.class, i -> !i.getColumn().equals("status") && !i.getColumn().equals("version"));将实体作为条件构造器函数这种应用场景一般是是前端传的查询条件全部都是等值条件才可以使用,像开发中经常要传一个日期范围(开始时间、结束时间)这种就不适合了,所以为了扩展性不太建议使用这种方式。也可以通过@TableField注解中的condition来改变默认的等值关系运算符,默认提供了等于、不等于、like 这三种,也可以自己直接定义字符串。虽然可以通过定义关系运算符字符串来改变默认的等值条件,但这样一定义所有使用实体作为条件的都会随着改变,还是有很大的局限性。个人感觉这个功能很局限。
public class User implements Serializable { /** * 姓名 */ @TableField(condition = SqlCondition.LIKE) private String name; } @Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE name LIKE CONCAT('%',?,'%') AND status=? User user = new User(); user.setName("六哥"); user.setStatus(0); QueryWrapper<User> queryWrapper = new QueryWrapper<>(user); userMapper.selectList(queryWrapper); }allEq就是全部eq(或个别isNull),也就使用value不为null的所有字段都使用=关系运算符,value为null翻译成SQL为 is null, 所有条件默认都是使用and逻辑运算符来连接。
allEq比将实体作为条件更加灵活,可以配置是否将null作为条件,可以自己写判断条件来决定是否加入到SQL中。
allEq(Map<R, V> params) allEq(Map<R, V> params, boolean null2IsNull) allEq(boolean condition, Map<R, V> params, boolean null2IsNull) allEq(BiPredicate<R, V> filter, Map<R, V> params) allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)参数说明:
params : key为数据库字段名,value为字段值。null2IsNull : 为true则在map的value为null时调用 isNull 方法,为false时则忽略value为null的, 默认为true。condition:表示是否将整个条件加入到SQL中,如果条件为true就加入,相当于MyBatis中的if标签。filter:过滤器,用于过滤每个条件,满足条件才会加入到SQL中。 @Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE (name IS NULL AND username = ?) Map<String, Object> paramMap = new HashMap<>(); paramMap.put("username", "sixbrother"); paramMap.put("name", null); QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.allEq(paramMap); } @Test void testMyBatisPlus() { // null2IsNull = false, value = null 的字段不加入到SQL语句中 // SELECT * FROM tbl_user WHERE (username = ?) Map<String, Object> paramMap = new HashMap<>(); paramMap.put("username", "sixbrother"); paramMap.put("name", null); QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.allEq(paramMap, false); } @Test void testMyBatisPlus() { // condition = false 则整个条件都不加入到SQL中 // SELECT * FROM tbl_user Map<String, Object> paramMap = new HashMap<>(); paramMap.put("username", "sixbrother"); paramMap.put("age", 30); paramMap.put("name", null); QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.allEq(false, paramMap, false); } @Test void testMyBatisPlus() { // filter中只有username满足条件,age没有大于30,name为null了都不满足条件 // SELECT * FROM tbl_user WHERE (username = ?) Map<String, Object> paramMap = new HashMap<>(); paramMap.put("username", "sixbrother"); paramMap.put("age", 30); paramMap.put("name", null); QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.allEq(true , (k, v) -> k.equals("username") || (v != null && Integer.parseInt(v.toString()) > 30) , paramMap , true); }EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False EXISTS 指定一个子查询,检测 行 的存在。
exists(String existsSql) exists(boolean condition, String existsSql) @Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE (EXISTS (select id from tbl_user where id = 1)) LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .exists("select id from tbl_user where id = 1"); userMapper.selectList(queryWrapper); }apply用于构造带有函数的条件,如日期函数等。该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!
apply(String applySql, Object... params) apply(boolean condition, String applySql, Object... params) @Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE (date_format(create_time, '%Y-%m-%d') = ?) LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .apply("date_format(create_time, '%Y-%m-%d') = {0}", "2020-10-07"); userMapper.selectList(queryWrapper); }func 方法(主要方便在出现if…else下调用不同方法能不断链),相当于MyBatis中的when … otherwise
@Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE (id <> ?) LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .func(i -> { if (false) { i.eq(User::getId, 1); } else { i.ne(User::getId, 1); } }); userMapper.selectList(queryWrapper); }and用于将多个条件括起来。
and(Consumer<Param> consumer) and(boolean condition, Consumer<Param> consumer) @Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE (username = ? AND (id >= ? AND age < ?)) LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .eq(User::getUsername, "sixbrother") .and(i -> i.ge(User::getId, 2).lt(User::getAge, 30)); userMapper.selectList(queryWrapper); }主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接) 注意:在SQL中or的优先级是低于and的优先级,所以在有and和or的时候注意使用小括号来表示一个整体条件。
or() or(boolean condition) // 用于将多个条件括起来 or(Consumer<Param> consumer) or(boolean condition, Consumer<Param> consumer) @Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE (username = ? OR age > ?) LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .eq(User::getUsername, "sixbrother") .or().gt(User::getAge, 30); userMapper.selectList(queryWrapper); } @Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE (username = ? OR (age >= ? AND id < ?)) LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .eq(User::getUsername, "sixbrother") .or(i -> i.ge(User::getAge, 30).lt(User::getId, 5)); userMapper.selectList(queryWrapper); }正常嵌套 不带 AND 或者 OR,一般直接作为where的第一个条件,此时不需要and或者or来连接条件。一般用于将第一个条件作为一个整体条件用小括号括住。
@Test void testMyBatisPlus() { // SELECT * FROM tbl_user WHERE ((name LIKE ? OR gender = ?)) LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .nested(i -> i.like(User::getName, "六哥").or().eq(User::getGender, 1)); userMapper.selectList(queryWrapper); }无视优化规则直接拼接到 sql 的最后,只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用,如果参数值是前台传过来的谨慎使用。
last(String lastSql) last(boolean condition, String lastSql) @Test void testMyBatisPlus() { // SELECT * FROM tbl_user limit 1 LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .last("limit 1"); userMapper.selectList(queryWrapper); }所有排序的字段都采用升续排序。
orderByAsc(R... columns) orderByAsc(boolean condition, R... columns) @Test void testMyBatisPlus() { // SELECT * FROM tbl_user ORDER BY id ASC,age ASC LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .orderByAsc(User::getId, User::getAge); userMapper.selectList(queryWrapper); }orderBy可以动态的统一设置升续或者降续。
orderBy(boolean condition, boolean isAsc, R... columns) @Test void testMyBatisPlus() { // SELECT * FROM tbl_user ORDER BY id ASC,age ASC LambdaQueryWrapper<User> queryWrapper = Wrappers.<User>lambdaQuery() .orderBy(true, true, User::getId, User::getAge); userMapper.selectList(queryWrapper); }