MyBatis-plus进阶之映射与条件构造器

MyBatis-plus进阶

映射

自动映射规则

  1. 表名和实体类名映射-》 表名user 实体类名User
  2. 字段名和实体类属性名映射-》字段名name 实体类属性名name

这里需要注意:User类里的 private String name; 这个name不是属性名,而是变量名。

那么什么是属性名呢?

类里面的属性对应的get方法,其方法名去掉"get"然后首字母小写对应的就是属性名,比如:

java 复制代码
// 属性名是name 映射到数据库的字段是name
public String getName() {
    return name;
}
// 属性名是testName 映射到数据库的字段是testName
public String getTestName() {
    return name;
}
  1. 字段名下划线命名方式和实体类属性小驼峰命名方式映射-》

    字段名 user_email 实体类属性名 userEmail

    MyBatis-plus支持这种映射规则,可以通过配置来设置:

    yaml 复制代码
    mybatis-plus:
      configuration:
        # 开启下划线到驼峰命名的映射
        map-underscore-to-camel-case: true

表映射@TableName注解

Pojo类通过@TableName注解指定映射的数据库表名,就会完成表名的映射。

@TableName注解主要应用在类名和数据库表名不一致的情况。

java 复制代码
// 表示User类映射到t_user表
@TableName("t_user")
public class User {
    private Long id;

    public String getName() {
        return name;
    }

    private String name;
    private Integer age;
    private String email;
}

那如果数据库表特别多的情况下,这样每个类都指定具体表名会很麻烦,此时就可以开启表映射的全局配置。

表映射的全局配置

yaml 复制代码
mybatis-plus:
  global-config:
	db-config:
	# 全局配置表名的前缀,这样会自动将Pojo类名的首字母小,并且加上前缀t_
	# 这样就不用使用@TableName来指定表名
      table-prefix: t_

字段映射

当数据库字段和表实体类的属性不一致时,可以使用@TableField注解改变字段和属性的映射,让注解中的名称和表字段保持一致。

java 复制代码
@TableField("user_email")
private String email;

此时的sql是:select id,user_email as email from user

有一个问题场景:当数据库表中的某个字段设置为desc时,注意:desc为数据库的关键字,此时查询的sql语句就是:

select id,name,desc from user

很明显,这样的sql执行时会报错。那么怎么解决呢?

给关键字加上分隔符就能执行成功:select id,name,`desc` from user

在Java中 给desc这个属性加上注解@TableField("`desc`") 也就是字段名加上分隔符就可以了。

字段失效

当数据库中有字段不想被查询时,可以使用@TableField(select= false)来隐藏这个字段。在拼接sql语句的时候就不会拼接这个字段

java 复制代码
// 查询时不会查出Email这个字段
@TableField(select = false)
private String email;

视图属性

实际开发中,有些字段不需要数据库存储,但需要展示,像这种实体类中存在但是数据库中不存在的字段,叫做视图字段。

这种字段可以通过@TableField(exist = false)注解来去掉这个字段,不让他作为查询或DML字段。

java 复制代码
@TableField(exist = false)
private String emailPhone;

条件构造器

MyBatis-plus的条件查询是基于面向对象的思想,条件查询使用对象来完成封装。

在实际开发中,只需要关注QueryWrapper和LambdaQueryWrapper这两个即可。

等值查询

eq 方法

下面的两种查询方式的结果是一样的。

java 复制代码
		// 使用 QueryWrapper
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        // 设置条件 name='test2'
        wrapper.eq("name", "test2");
        User user1 = userService.getOne(wrapper);
        System.out.println(user1);

        // 使用LambdaQueryWrapper,这种方式可以避免字段名写错
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getName, "test2");
        User user2 = userService.getOne(lambdaQueryWrapper);
        System.out.println(user2);

null的判断

当前端传来的查询条件为null时。此时用户希望不需要以此条件进行查询,我们就不需要进行查询拼接。

可以使用下面的方式进行判断处理:

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
String name = "test2";
// 当name为null或者""时,不作为查询拼接
lambdaQueryWrapper.eq(StringUtils.isNotBlank(name),User::getName, name);
User user2 = userService.getOne(lambdaQueryWrapper);
System.out.println(user2);

多条件查询

第一种方式:可以通过多个eq 来构建多条件查询

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
String name = "test2";
lambdaQueryWrapper.eq(User::getName, name);
lambdaQueryWrapper.eq(User::getAge, 12);
User user2 = userService.getOne(lambdaQueryWrapper);
System.out.println(user2);

此时对应的sql是select * from t_user where name='test2' and age =12

第二种方式:allEq 方法,通过将查询条件封装在一个map中,然后调用allEq方法,实现多条件查询

java 复制代码
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("name", "test2");
hashMap.put("age", 12);
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
 // 第二个参数表示,当map中的值为null时,不作为查询条件进行拼接
queryWrapper.allEq(hashMap,false);
User user3 = userService.getOne(lambdaQueryWrapper);
System.out.println(user3);

ne 不等值查询

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
String name = "test2";
lambdaQueryWrapper.ne(User::getName, name);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where name <> 'test2'

范围查询

gt 大于

java 复制代码
 		LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.gt(User::getAge, 12);
        List<User> userList = userService.list(lambdaQueryWrapper);
        System.out.println(userList);

对应的sql:select * from t_user where age > 12

ge 大于等于

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.ge(User::getAge, 12);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age >= 12

lt 小于

复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.lt(User::getAge, 12);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age < 12

le 小于等于

复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.le(User::getAge, 12);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age <= 12

between 范围内

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 查询年龄在12-36之间
lambdaQueryWrapper.between(User::getAge, 12,36);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age between 12 and 36 查询结果包含年龄为12和36的数据。

notBetween 范围外

复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 查询年龄不在12-36之间
lambdaQueryWrapper.between(User::getAge, 12,36);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age not between 12 and 36

模糊查询

like

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.like(User::getName, "张");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where name like '%张%'

notLike

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.notLike(User::getName, "张");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where name not like '%张%'

likeLeft

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.likeLeft(User::getName, "张");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where name like '%张' 查询name以'张'结尾

likeRight

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.likeRight(User::getName, "张");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where name like '张%' 查询name以'张'开头

判空查询

isNull

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.isNull(User::getEmail);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where email is null

isNotNull

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.isNotNull(User::getEmail);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where email is not null

包含查询 in

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
ArrayList<Integer> arrayList = new ArrayList<>();
Collections.addAll(arrayList, 21, 22, 23);
lambdaQueryWrapper.in(User::getAge, arrayList);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age in (21,22,23)

不包含查询 notIn

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
ArrayList<Integer> arrayList = new ArrayList<>();
Collections.addAll(arrayList, 21, 22, 23);
lambdaQueryWrapper.notIn(User::getAge, arrayList);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age not in (21,22,23)

包含查询 inSql

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 查询条件直接写死
// lambdaQueryWrapper.inSql(User::getAge, "11,12,13");
// 查询条件时一条sql
lambdaQueryWrapper.inSql(User::getAge, "select age from k_user where age < 20");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

对应的sql:select * from t_user where age in (11,12,13)

​ select * from t_user where age in (select age from k_user where age < 20)

不包含查询 notInSql

调用方式与上面类似,这里不再举例

分组查询 groupBy

java 复制代码
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 分组字段
wrapper.groupBy("age");
// 查询字段
wrapper.select("age,count(*) as field_count");
List<Map<String, Object>> mapList =  userService.listMaps(wrapper);
System.out.println(mapList);

对应的sql :select age,count(*) as field_count from t_user group by age

聚合查询 having

java 复制代码
  		QueryWrapper<User> wrapper = new QueryWrapper<>();
        // 分组字段
        wrapper.groupBy("age");
        // 查询字段
        wrapper.select("age,count(*) as field_count");
		// 聚合条件筛选
        wrapper.having("field_count > 10");
        List<Map<String, Object>> mapList =  userService.listMaps(wrapper);
        System.out.println(mapList);

对应的sql :select age,count(*) as field_count from t_user group by age having field_count > 10

排序查询

  1. orderByAsc 升序
java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByAsc(User::getAge,User::getId);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql :select * from t_user order by age asc,id asc
  1. orderByDesc 降序
java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.orderByDesc(User::getAge,User::getId);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql :select * from t_user order by age desc,id desc
  1. orderBy 有升序有降序

    java 复制代码
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    // 参数1:如果排序的字段值为null,是否还参与排序
    // 参数2:是否是升序
    // 参数3:排序的字段
    lambdaQueryWrapper.orderBy(true,true,User::getAge);
    lambdaQueryWrapper.orderBy(true,false,User::getId);
    List<User> userList = userService.list(lambdaQueryWrapper);
    System.out.println(userList);
    
    // 对应的sql :select * from t_user order by age asc,id desc

内嵌逻辑查询 func

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 根据不同情况来选择拼接不同的查询条件
lambdaQueryWrapper.func(new Consumer<LambdaQueryWrapper<User>>() {
    @Override
    public void accept(LambdaQueryWrapper<User> userLambdaQueryWrapper) {
        if (1==1){
            userLambdaQueryWrapper.eq(User::getAge,22);
        }else {
            userLambdaQueryWrapper.ne(User::getAge,22);
        }
    }
});
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql:select * from t_user where age = 22

逻辑查询

  1. and

    正常拼接默认就是and,比如:

    java 复制代码
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    // 根据不同情况来选择拼接不同的查询条件
    lambdaQueryWrapper.gt(User::getAge,12).lt(User::getAge,22);
    List<User> userList = userService.list(lambdaQueryWrapper);
    System.out.println(userList);
    
    // 对应的sql;select * from t_user where age > 12 and age < 22

    and的嵌套查询:

    java 复制代码
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.eq(User::getName, "张三").and(u -> u.gt(User::getAge, 22).or().lt(User::getAge, 20));
    List<User> userList = userService.list(lambdaQueryWrapper);
    System.out.println(userList);
    
    // 对应的sql;select * from t_user where name = '张三' and (age > 22 or age < 20)
  2. or

    java 复制代码
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.gt(User::getAge, 22).or().lt(User::getAge, 20);
    List<User> userList = userService.list(lambdaQueryWrapper);
    System.out.println(userList);
    
    // 对应的sql;select * from t_user where age > 22 or age < 20

    or 的嵌套查询

    java 复制代码
    LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
    lambdaQueryWrapper.eq(User::getName, "张三").or(u->u.gt(User::getAge,20).lt(User::getAge,30));
    List<User> userList = userService.list(lambdaQueryWrapper);
    System.out.println(userList);
    
    // 对应的sql;select * from t_user where name = '张三' or (age > 20 and age < 30)
  3. nested

    .nested() 用于嵌套条件分组 的核心方法,作用是将一组条件用 () 包裹起来,形成独立的条件块,避免多个条件之间的逻辑运算优先级混乱。

    需求:查询 age > 20 且(name = "张三"email 包含 "test")的用户。

    java 复制代码
    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
        .gt(User::getAge, 20) // 外层条件:age>20
        .nested(qw -> qw       // 嵌套分组:(name=张三 OR email包含test)
            .eq(User::getName, "张三")
            .or()
            .like(User::getEmail, "test")
        );
    List<User> userList = userService.list(lambdaQueryWrapper);
    System.out.println(userList);
    
    // 对应的sql;select * from t_user WHERE age > 20 AND (name = '张三' OR email LIKE '%test%')

自定义查询 apply

apply方法的参数是字符串,会跟在sql语句where的后面,在复杂查询的应用场景中使用。

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.apply("id=1");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql;select * from t_user where id = 1

last 查询

last 方法允许你直接在查询的最后添加一个 SQL 片段

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.last("limit 0,10");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql;select * from t_user limit 0,10

注意:last 方法只能调用一次,多次调用将以最后一次为准。比如:

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.last("where age =22");
lambdaQueryWrapper.last("and name = '张三'");
lambdaQueryWrapper.last("limit 0,10");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql;select * from t_user limit 0,10

exists查询

exists 方法用于在查询中添加一个 EXISTS 子查询。通过调用 exists 方法,可以将一个完整的 SQL 子查询作为 EXISTS 条件添加到主查询中。

exists表示当子查询有返回结果时才执行主查询,如果子查询没有返回结果,那么不执行主查询。

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.exists("select id from t_user where age = 1");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql;select * from t_user WHERE EXISTS (select id from t_user where age = 1)

notExists查询

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.notExists("select id from t_user where age = 1");
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql;select * from t_user WHERE NOT EXISTS (select id from t_user where age = 1)

select查询

select 方法用于设置查询的字段。通过调用 select 方法,可以指定在查询结果中包含哪些字段,从而实现字段级别的查询定制。

java 复制代码
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.select(User::getId, User::getName, User::getAge);
List<User> userList = userService.list(lambdaQueryWrapper);
System.out.println(userList);

// 对应的sql;select id,name,age from t_user
相关推荐
Seven974 小时前
NIO的零拷贝如何实现高效数据传输?
java
架构师沉默18 小时前
别又牛逼了!AI 写 Java 代码真的行吗?
java·后端·架构
后端AI实验室1 天前
我把一个生产Bug的排查过程,交给AI处理——20分钟后我关掉了它
java·ai
凉年技术1 天前
Java 实现企业微信扫码登录
java·企业微信
狂奔小菜鸡1 天前
Day41 | Java中的锁分类
java·后端·java ee
hooknum1 天前
学习记录:基于JWT简单实现登录认证功能-demo
java
程序员Terry1 天前
同事被深拷贝坑了3小时,我教他原型模式的正确打开方式
java·设计模式
NE_STOP1 天前
MyBatis-缓存与注解式开发
java
码路飞1 天前
不装 OpenClaw,我用 30 行 Python 搞了个 QQ AI 机器人
java