MyBatis-Plus之DQL编程控制

news/2024/4/29 8:12:26/文章来源:https://blog.csdn.net/qq_37726813/article/details/128028110

增删改查四个操作中,查询是非常重要的也是非常复杂的操作,本次介绍的有:

  • 条件查询方式
  • 查询投影
  • 查询条件设定
  • 字段映射与表名映射

1. 条件查询

1.1 条件查询的类

  • MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合。

这个我们在前面都有见过,比如查询所有和分页查询的时候,都有看到过一个Wrapper类,这个类就是用来构建查询条件的,如下图所示:

在这里插入图片描述

那么条件查询如何使用Wrapper来构建呢?

1.2 环境构建

在构建条件查询之前,我们先来准备下环境

  • 创建一个SpringBoot项目

  • pom.xml中添加对应的依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.dcxuexi</groupId><artifactId>springboot_mp_03_dql</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot_mp_03_dql</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.11</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>
    
  • 编写UserDao接口

    @Mapper
    public interface UserDao extends BaseMapper<User> {
    }
    
  • 编写模型类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @TableName(value = "platform_user")
    public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email;private String userName;private String branchName;
    }
    
  • 编写引导类

    @SpringBootApplication
    public class SpringbootMp03DqlApplication {public static void main(String[] args) {SpringApplication.run(SpringbootMp03DqlApplication.class, args);}}
    
  • 编写配置文件

    spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatisusername: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSource
    mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  #打印SQL日志到控制台
    
  • 编写测试类

    @SpringBootTest
    class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectById() {User user = userDao.selectById(146);System.out.println("user = " + user);}}
    

    最终创建的项目结构为:

在这里插入图片描述

  • 测试的时候,控制台打印的日志比较多,速度有点慢而且不利于查看运行结果,所以接下来我们把这个日志处理下:

    • 取消初始化spring日志打印,resources目录下添加logback.xml,名称固定,内容如下:

      <?xml version="1.0" encoding="UTF-8"?>
      <configuration>
      </configuration>
      
    • 取消MybatisPlus启动banner图标

      在这里插入图片描述

      application.yml添加如下内容:

      mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  #打印SQL日志到控制台global-config:banner: false # 关闭mybatisplus启动图标
      
    • 取消SpringBoot的log打印

      在这里插入图片描述

      application.yml添加如下内容:

      spring:main:banner-mode: off # 关闭SpringBoot启动图标(banner)
      

解决控制台打印日志过多的相关操作可以不用去做,一般会被用来方便我们查看程序运行的结果。

1.3 构建条件查询

在进行查询的时候,我们的入口是在Wrapper这个类上,因为它是一个接口,所以我们需要去找它对应的实现类,关于实现类也有很多,说明我们有多种构建查询条件对象的方式,

在这里插入图片描述

  1. 先来看第一种:QueryWrapper
@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();queryWrapper.lt("user_id",10);List<User> userList = userDao.selectList(queryWrapper);userList.forEach(System.out::println);}
}
  • lt:小于(<) ,最终的sql语句为

    SELECT user_id,email,user_name,branch_name FROM platform_user WHERE (user_id < ?)
    

在这里插入图片描述

第一种方式介绍完后,有个小问题就是在写条件的时候,容易出错,比如user_id写错,就会导致查询不成功

  1. 接着来看第二种:QueryWrapper的基础上使用lambda
@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//queryWrapper.lt("user_id",10);queryWrapper.lambda().lt(User::getUserId,10);List<User> userList = userDao.selectList(queryWrapper);userList.forEach(System.out::println);}
}
  • User::getAget,为lambda表达式中的,类名::方法名,最终的sql语句为:
SELECT user_id,email,user_name,branch_name FROM platform_user WHERE (user_id < ?)

注意: 构建LambdaQueryWrapper的时候泛型不能省。

此时我们再次编写条件的时候,就不会存在写错名称的情况,但是qw后面多了一层lambda()调用

  1. 接着来看第三种:LambdaQueryWrapper
@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){//QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//queryWrapper.lt("user_id",10);//queryWrapper.lambda().lt(User::getUserId,10);LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.lt(User::getUserId,10);List<User> userList = userDao.selectList(lambdaQueryWrapper);userList.forEach(System.out::println);}
}

这种方式就解决了上一种方式所存在的问题。

1.4 多条件构建

上面的三种构建查询对象的方式,每一种都有自己的特点,所以用哪一种都行,刚才都是一个条件,那如果有多个条件该如何构建呢?

需求:查询数据库表中,用户ID在10到20之间的用户信息

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.gt(User::getUserId,10);lambdaQueryWrapper.lt(User::getUserId,20);List<User> userList = userDao.selectList(lambdaQueryWrapper);userList.forEach(System.out::println);}
}
  • gt:大于(>),最终的SQL语句为

    SELECT user_id,email,user_name,branch_name FROM platform_user WHERE (user_id > ? AND user_id < ?)
    
  • 构建多条件的时候,可以支持链式编程

    @SpringBootTest
    class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.gt(User::getUserId,10).lt(User::getUserId,20);//lambdaQueryWrapper.lt(User::getUserId,20);List<User> userList = userDao.selectList(lambdaQueryWrapper);userList.forEach(System.out::println);}
    }
    

需求:查询数据库表中,用户ID小于10或大于20的数据

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.lt(User::getUserId,10).or().gt(User::getUserId,20);//lambdaQueryWrapper.lt(User::getUserId,20);List<User> userList = userDao.selectList(lambdaQueryWrapper);userList.forEach(System.out::println);}
}
  • or()就相当于我们sql语句中的or关键字,不加默认是and,最终的sql语句为:

    SELECT user_id,email,user_name,branch_name FROM platform_user WHERE (user_id < ? OR user_id > ?)
    

1.5 null判定

在这里插入图片描述

  • 我们在做条件查询的时候,一般会有很多条件可以供用户进行选择查询。
  • 这些条件用户可以选择使用也可以选择不使用,比如我要查询价格在10000以上的电脑
  • 在输入条件的时候,价格有一个区间范围,按照需求只需要在第一个价格输入框中输入10000
  • 后台在做价格查询的时候,一般会让 price>值1 and price <值2
  • 因为前端没有输入值2,所以如果不处理的话,就会出现 price>10000 and price < null问题
  • 这个时候查询的结果就会出问题,具体该如何解决?

需求:查询数据库表中,根据输入用户ID范围来查询符合条件的记录

用户在输入值的时候,

​ 如果只输入第一个框,说明要查询大于该用户ID的用户

​ 如果只输入第二个框,说明要查询小于该用户ID的用户

​ 如果两个框都输入了,说明要查询用户ID在两个范围之间的用户

思考第一个问题:后台如果想接收前端的两个数据,该如何接收?

我们可以使用两个简单数据类型,也可以使用一个模型类,但是User类中目前只有一个userId属性,如:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email;private String userName;private String branchName;
}

使用一个userId属性,如何去接收页面上的两个值呢?这个时候我们有两个解决方案

方案一:添加属性userId2,这种做法可以但是会影响到原模型类的属性内容

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email;private String userName;private String branchName;private Integer userId2;
}

方案二:新建一个模型类,让其继承User类,并在其中添加userId2属性,UserQuery在拥有User属性后同时添加了userId2属性。

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email;private String userName;private String branchName;
}
@Data
public class QueryUser extends User {private Integer userId2;
}

环境准备好后,我们来实现下刚才的需求:

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){//模拟页面传递过来的查询数据QueryUser queryUser = new QueryUser();queryUser.setUserId2(50);queryUser.setUserId(20);LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();if (null != queryUser.getUserId2()){lambdaQueryWrapper.lt(User::getUserId,queryUser.getUserId2());}if (null != queryUser.getUserId()){lambdaQueryWrapper.gt(User::getUserId,queryUser.getUserId());}List<User> userList = userDao.selectList(lambdaQueryWrapper);userList.forEach(System.out::println);}
}

上面的写法可以完成条件为非空的判断,但是问题很明显,如果条件多的话,每个条件都需要判断,代码量就比较大,来看MP给我们提供的简化方式:

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){//模拟页面传递过来的查询数据QueryUser queryUser = new QueryUser();queryUser.setUserId2(50);queryUser.setUserId(20);LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.lt(null != queryUser.getUserId2(),User::getUserId,queryUser.getUserId2());lambdaQueryWrapper.gt(null != queryUser.getUserId(),User::getUserId,queryUser.getUserId());List<User> userList = userDao.selectList(lambdaQueryWrapper);userList.forEach(System.out::println);}
}
  • lt()方法

    在这里插入图片描述

    condition为boolean类型,返回true,则添加条件,返回false则不添加条件

2. 查询投影

2.1 查询指定字段

目前我们在查询数据的时候,什么都没有做默认就是查询表中所有字段的内容,我们所说的查询投影即不查询所有字段,只查询出指定内容的数据。

具体如何来实现:

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();lambdaQueryWrapper.select(User::getUserName,User::getEmail);List<User> userList = userDao.selectList(lambdaQueryWrapper);userList.forEach(System.out::println);}
}
  • select(…)方法用来设置查询的字段列,可以设置多个,最终的sql语句为:

    SELECT user_name,email FROM platform_user
    
  • 如果使用的不是lambda,就需要手动指定字段

    @SpringBootTest
    class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){//LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();QueryWrapper<User> queryWrapper = new QueryWrapper<User>();queryWrapper.select("user_name","email");List<User> userList = userDao.selectList(queryWrapper);userList.forEach(System.out::println);}
    }
    
    • 最终的sql语句为:SELECT user_name,email FROM platform_user

2.2 聚合查询

需求:聚合函数查询,完成count、max、min、avg、sum的使用

count:总记录数

max:最大值

min:最小值

avg:平均值

sum:求和

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//queryWrapper.select("count(*) as num");//queryWrapper.select("max(user_id) as maxId");//queryWrapper.select("min(user_id) as minId");//queryWrapper.select("avg(user_id) as avgId");queryWrapper.select("sum(user_id) as sumId");List<Map<String, Object>> mapList = userDao.selectMaps(queryWrapper);System.out.println(mapList);}
}

在这里插入图片描述

为了在做结果封装的时候能够更简单,我们将上面的聚合函数都起了个名称,方面后期来获取这些数据

2.3 分组查询

需求:分组查询,完成 group by的查询使用

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();queryWrapper.select("count(*) as num , branch_name");queryWrapper.groupBy("branch_name");List<Map<String, Object>> mapList = userDao.selectMaps(queryWrapper);System.out.println(mapList);}
}
  • groupBy为分组,最终的sql语句为

    SELECT count(*) as num , branch_name FROM platform_user GROUP BY branch_name
    

注意:

  • 聚合与分组查询,无法使用lambda表达式来完成
  • MP只是对MyBatis的增强,如果MP实现不了,我们可以直接在DAO接口中使用MyBatis的方式实现

3. 查询条件

前面我们只使用了lt()和gt(),除了这两个方法外,MP还封装了很多条件对应的方法,重点把MP提供的查询条件方法进行介绍下。

MP的查询条件有很多:

  • 范围匹配(> 、 = 、between)
  • 模糊匹配(like)
  • 空判定(null)
  • 包含性匹配(in)
  • 分组(group)
  • 排序(order)
  • ……

3.1 等值查询

需求:根据用户名和归属公司查询用户信息

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();queryWrapper.lambda().eq(User::getUserName,"fenjinba").eq(User::getBranchName, "奋进吧");User user = userDao.selectOne(queryWrapper);System.out.println("user = " + user.toString());}
}
  • eq(): 相当于 =,对应的sql语句为

    SELECT user_id,email,user_name,branch_name FROM platform_user WHERE (user_name = ? AND branch_name = ?)
    
  • selectList:查询结果为多个或者单个

  • selectOne:查询结果为单个

3.2 范围查询

需求:对年龄进行范围查询,使用lt()、le()、gt()、ge()、between()进行范围查询

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();queryWrapper.lambda().between(User::getUserId,10,20);List<User> userList = userDao.selectList(queryWrapper);userList.forEach(System.out::println);}
}
  • gt():大于(>)

  • ge():大于等于(>=)

  • lt():小于(<)

  • lte():小于等于(<=)

  • between():between ? and ?

    SELECT user_id,email,user_name,branch_name FROM platform_user WHERE (user_id BETWEEN ? AND ?)
    

3.3 模糊查询

需求:查询表中branch_name属性的值以上海开头的用户信息,使用like进行模糊查询

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//queryWrapper.lambda().between(User::getUserId,10,20);queryWrapper.lambda().like(User::getBranchName,"上海");List<User> userList = userDao.selectList(queryWrapper);userList.forEach(System.out::println);}
}
  • like():前后加百分号,如 %上海%
  • likeLeft():前面加百分号,如 %上海
  • likeRight():后面加百分号,如 上海%

3.4 排序查询

需求上海查询所有数据,然后按照user_id降序

@SpringBootTest
class SpringbootMp03DqlApplicationTests {@Autowiredprivate UserDao userDao;@Testvoid testSelectAll(){QueryWrapper<User> queryWrapper = new QueryWrapper<User>();//condition :条件,返回boolean,当condition为true,进行排序,如果为false,则不排序//isAsc:是否为升序,true为升序,false为降序//columns:需要操作的列queryWrapper.lambda().orderBy(true,true,User::getUserId);List<User> userList = userDao.selectList(queryWrapper);userList.forEach(System.out::println);}
}

除了上面演示的这种实现方式,还有很多其他的排序方法可以被调用,如图:

在这里插入图片描述

  • orderBy排序
    • condition:条件,true则添加排序,false则不添加排序
    • isAsc:是否为升序,true升序,false降序
    • columns:排序字段,可以有多个
  • orderByAsc/Desc(单个column):按照指定字段进行升序/降序
  • orderByAsc/Desc(多个column):按照多个字段进行升序/降序
  • orderByAsc/Desc
    • condition:条件,true添加排序,false不添加排序
    • 多个columns:按照多个字段进行排序

除了上面介绍的这几种查询条件构建方法以外还会有很多其他的方法,比如isNull,isNotNull,in,notIn等等方法可供选择,具体参考官方文档的条件构造器来使用,暂时不介绍了。

4. 映射匹配兼容性

前面我们已经能从表中查询出数据,并将数据封装到模型类中,这整个过程涉及到一张表和一个模型类:

CREATE TABLE `user` (`user_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,`email` varchar(60) NOT NULL DEFAULT '',`user_name` varchar(60) NOT NULL DEFAULT '',`branch_name` varchar(30) DEFAULT NULL,PRIMARY KEY (`user_id`) USING BTREE,KEY `idx_platform_user_id_name` (`user_name`) USING BTREE,KEY `idx_platform_user_email` (`email`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
public class User {private Integer userId;private String email;private String userName;private String company;
}

之所以数据能够成功的从表中获取并封装到模型对象中,原因是表的字段列名和模型类的属性名一样。

那么问题就来了:

问题1:表字段与编码属性设计不同步

当表的列名和模型类的属性名发生不一致,就会导致数据封装不到模型对象,这个时候就需要其中一方做出修改,那如果前提是两边都不能改又该如何解决?

MP给我们提供了一个注解@TableField,使用该注解可以实现模型类属性名和表的列名之间的映射关系

public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email;private String userName;@TableId(value = "branch_name")private String company;
}

问题2:编码中添加了数据库中未定义的属性

当模型类中多了一个数据库表不存在的字段,就会导致生成的sql语句中在select的时候查询了数据库不存在的字段,程序运行就会报错,错误信息为:nested exception is java.sql.SQLSyntaxErrorException: Unknown column '多出来的字段名称' in 'field list'

具体的解决方案用到的还是@TableField注解,它有一个属性叫exist,设置该字段是否在数据库表中存在,如果设置为false则不存在,生成sql语句查询的时候,就不会再查询该字段了。

public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email;private String userName;@TableField(value = "branch_name")private String company;@TableField(exist = false)private String address; //该字段数据表中不存在
}

问题3:采用默认查询开放了更多的字段查看权限

查询表中所有的列的数据,就可能把一些敏感数据查询到返回给前端,这个时候我们就需要限制哪些字段默认不要进行查询。解决方案是@TableField注解的一个属性叫select,该属性设置默认是否需要查询该字段的值,true(默认值)表示默认查询该字段,false表示默认不查询该字段。

public class User {@TableId(type = IdType.AUTO)private Integer userId;@TableField(select = false)private String email; //不查询该字段private String userName;@TableField(value = "branch_name")private String company;@TableField(exist = false)private String address; //该字段数据表中不存在
}

知识点1:@TableField

名称@TableField
类型属性注解
位置模型类属性定义上方
作用设置当前属性对应的数据库表中的字段关系
相关属性value(默认):设置数据库表字段名称
exist:设置属性在数据库表字段中是否存在,默认为true,此属性不能与value合并使用
select:设置属性是否参与查询,此属性与select()映射配置不冲突

问题4::表名与编码开发设计不同步

该问题主要是表的名称和模型类的名称不一致,导致查询失败,这个时候通常会报如下错误信息:

CREATE TABLE `platform_user` (`user_id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,`email` varchar(60) NOT NULL DEFAULT '',`user_name` varchar(60) NOT NULL DEFAULT '',`branch_name` varchar(30) DEFAULT NULL,PRIMARY KEY (`user_id`) USING BTREE,KEY `idx_platform_user_id_name` (`user_name`) USING BTREE,KEY `idx_platform_user_email` (`email`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
public class User {@TableId(type = IdType.AUTO)private Integer userId;@TableField(select = false)private String email; //不查询该字段private String userName;@TableField(value = "branch_name")private String company;@TableField(exist = false)private String address; //该字段数据表中不存在
}

nested exception is java.sql.SQLSyntaxErrorException: Table 'mybatis.user' doesn't exist

翻译过来就是数据库中的表不存在。

解决方案是使用MP提供的另外一个注解@TableName来设置表与模型类之间的对应关系。

@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;@TableField(select = false)private String email; //不查询该字段private String userName;@TableField(value = "branch_name")private String company;@TableField(exist = false)private String address; //该字段数据表中不存在
}

知识点2:@TableName

名称@TableName
类型类注解
位置模型类定义上方
作用设置当前类对应于数据库表关系
相关属性value(默认):设置数据库表名称

代码演示

接下来我们使用案例的方式把刚才的知识演示下:

步骤1:修改数据库表user为platform_user

直接查询会报错,原因是MP默认情况下会使用模型类的类名首字母小写当表名使用。

在这里插入图片描述

步骤2:模型类添加@TableName注解

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email; private String userName;private String branchName;
}

步骤3:将字段branch_name修改成company

直接查询会报错,原因是MP默认情况下会使用模型类的属性名当做表的列名使用

在这里插入图片描述

步骤4:使用@TableField映射关系

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email; private String userName;@TableField(value = "branch_name")private String company;
}

步骤5:添加一个数据库表不存在的字段

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email; private String userName;@TableField(value = "branch_name")private String company;private String address; //该字段数据表中不存在
}

直接查询会报错,原因是MP默认情况下会查询模型类的所有属性对应的数据库表的列,而address不存在

在这里插入图片描述

步骤6:使用@TableField排除字段

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;private String email; private String userName;@TableField(value = "branch_name")private String company;@TableField(exist = false)private String address; //该字段数据表中不存在
}

步骤7:查询时将email隐藏

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "platform_user")
public class User {@TableId(type = IdType.AUTO)private Integer userId;@TableField(select = false)private String email; //不查询该字段private String userName;@TableField(value = "branch_name")private String company;@TableField(exist = false)private String address; //该字段数据表中不存在
}

项目代码

  • gitee 代码下载

  • github 代码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_225379.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

精彩回顾|关系网络赋能银行数字化转型的应用与实践

本文是根据11月10日Galaxybase图创课堂&#xff1a;乘金融科技之风&#xff1a;关系网络赋能银行数字化转型的应用与实践整理&#xff0c;错过的小伙伴们可以观看回放&#xff1a;https://uao.so/pct862806 精彩回顾 近年&#xff0c;知识图谱的重要性和实际应用逐步呈上升趋…

C++入门教程||C++while循环

whlie 语法 C 中 while 循环的语法&#xff1a; while(condition) {statement(s); } 在这里&#xff0c;statement(s) 可以是一个单独的语句&#xff0c;也可以是几个语句组成的代码块。condition 可以是任意的表达式&#xff0c;当为任意非零值时都为真。当条件为真时执行…

企业实战!基于Harbor搭建企业镜像仓库

企业实战&#xff01;基于Harbor搭建企业镜像仓库 虽然Docker官方提供了Docker Hub作为公共的Registry服务器&#xff0c;给到用户进行镜像的保存和管理工作。但对于企业而言&#xff0c;考虑到安全性和网络效率等原因&#xff0c;通常会搭建私有的Registry服务器&#xff0c;用…

程序员在平台兼职接单,月入30K,方法我全写出来了!(附接单渠道和注意事项)

本月兼职的收入又到账了&#xff0c;程序员副业实在是太香了&#xff01; 虽然这点小钱还远远达不到财富自由&#xff0c;也比不上那些真正的大佬&#xff0c;但在这个行业寒冬里&#xff0c;能有一笔相对稳定的收入&#xff0c;作为全职之外的补充&#xff0c;还是让人倍感踏实…

闪电连接算法之Python实现

文章目录简介原理Python实现简介 LAPO&#xff0c;即闪电连接优化(Lightning Attachment Procedure Optimization)&#xff0c;听名字就知道是受到了闪电的刺激&#xff0c;而获得灵感的一种算法。 为了走进LAPO的内心&#xff0c;于是上网搜了一下闪电的图片 呃不好意思&…

Eigen Segmentation fault (core dumped)

不会GDB吃大亏问题描述&#xff1a;解法&#xff1a;写在前面的话&#xff1a;我是PCL新手。也是Cmake新手。Eigen有点折腾人。 问题描述&#xff1a; 在调用PCL库实现一些有趣的功能&#xff0c;考虑到考虑到兼容不同平台&#xff0c;现状如下&#xff1a; VS2015&#xff1…

【新知实验室】腾讯云TRTC初体验

一、前言 今年腾讯云音视频发布了“三合一”的RT-ONE™网络。该网络整合了腾讯云实时通信网络&#xff08;TRTC&#xff09;、即时通信网络&#xff08;IM&#xff09;以及流媒体分发网络&#xff08;CDN&#xff09;三张网络&#xff0c;为业界最完整的音视频通信PaaS平台构建…

Pr 时间重映射卡点

哈喽&#xff0c;各位小伙伴&#xff01;今天我们来学习一下如何通过用Pr时间重映射做出卡点的效果~ 卡点音乐 一首适合卡点&#xff08;群青为例&#xff09;的音乐可以帮助我们更好的掌握视频的节奏&#xff0c;卡点可以采用手动卡点&#xff0c;方法可以通过在峰值最高处标…

使用SSM搭建图书商城管理系统(完整过程介绍、售后服务哈哈哈)

经过几位下载同学的反应、大部分运行未成功的原因有以下几点、特此记录以下。代码是完全没有问题的 项目地址&#xff1a;https://download.csdn.net/download/weixin_43304253/85811914 代码运行环境&#xff1a; tomcat&#xff1a;8 IDEA&#xff1a;2020 JDK&#xff1a;1…

Handler 原理

线程的应用场景 Android是单线程模型&#xff0c;Activity、Service、Broadcast等组件的创建&#xff0c;都是在主线程完成的&#xff0c;即UI线程。但如果需要执行一些耗时的操作时&#xff0c;比如&#xff1a;I/O的读写、大文件的读写、数据库操作以及网络上传和下载等操作都…

关于数据治理工具的选型,你了解多少?

数据治理的本质是盘点数据资产、治理数据质量&#xff0c;实施数据全生命周期的管理&#xff0c;这里面包括了建组织、立制度或者使用一款数据治理的软件帮助企业开展数据治理的相关工作等等。根据不同的数据治理项目特点&#xff0c;会用到不同的技术或工具。拥有一套趁手好用…

pdf生成:puppeteer

一、Puppeteer Puppeteer是Google Chrome团队出品的一款无界面Chrome工具&#xff0c;它提供了丰富的API&#xff0c;让开发者像鼠标一样控制浏览器的各种行为。Puppeteer是一个Node库&#xff0c;提供发了一个高级API来通过DevTools协议控制Chromium或Chrome。Puppeteer默认以…

LVGL学习笔记

芯片启动到LVGL初始化完成大体流程如下: 界面增加打印后代码如下: static void drag_event_handler(lv_event_t * e) {lv_obj_t * obj lv_event_get_target(e);lv_indev_t * indev lv_indev_get_act();if(indev NULL) return;lv_point_t vect;lv_indev_get_vect(indev, …

scala语法(一)(有java基础速学)

在拥有java基础上学习scala&#xff0c;注意以下几点 1. 变量声明 var | val 变量名 [: 变量类型] 变量值 val name: String "nico" 声明变量时&#xff0c;类型可以省略&#xff08;就是叫 类型推断&#xff09; val name "nico"类型确定后&#xff…

【面试题】JS基础-异步

1. 异步 1.1 为什么要异步&#xff1f; JS是单线程语言&#xff0c;只能同时做一件事。JS和DOM渲染共用同一个线程&#xff0c;因为JS可修改DOM结构。当遇到等待的情况时&#xff0c;例如网络请求、定时任务&#xff0c;程序不能卡住。所以需要异步来解决JS单线程等待的问题&…

Git -- submoudule子模块使用

文章目录子模块的作用添加子模块拉取带子模块的项目修改子模块代码子模块的作用 通常情况下&#xff0c;我们做项目时会有几个业务功能区分比较明确的模块&#xff0c;比如简单来说&#xff0c;一个项目我们可以分为认证授权模块、工具类模块、常规业务模块。 而像认证…

【Redis技术探索】「高可用架构模式」哨兵(sentinel)模式实现主从故障互切换模式详解

哨兵&#xff08;sentinel&#xff09;模式实现主从故障互切换模式详解Redis的多种模式Redis单机模式Redis单机模式的优点Redis单机模式的缺点Redis主从复制旧版本配置新版本配置查看主节点信息主从模式的优点主从复制的弊端Redis哨兵模式分析哨兵结构组成哨兵模式的主从切换Re…

重点,一文掌握ReentrantLock加解锁原理!|原创

本文详细讲解了 ReentrantLock 加锁和释放锁的原理&#xff0c;以及和 Synchronized 的对比。本文较长&#xff0c;建议收藏&#xff01;点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达简要总结 ReentrantLock实现原理&#xff1a;volati…

Android入门第33天-Android里的弹出式对话框

简介 Android Studio里在4.0前有一种ProgressDialog&#xff0c;这个已经淘汰了。我们完全可以使用ProgressBar来取代。但是还有一种Dialog叫PopWindow&#xff0c;它是一种“可阻塞式Dialog”。即弹出后除非你给它一个“动作”否则就一直显示在那。 今天我们就来看看这种Dia…

【Linux】基础IO —— 动静态库的制作与使用

&#x1f308;欢迎来到Linux专栏~~动静态库的制作与使用 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自…