• MyBatis-Plus DQL与其他知识点


     哈喽~大家好,这篇来看看MyBatis-Plus DQL与其他知识点

     🥇个人主页:个人主页​​​​​               

    🥈 系列专栏: 【Java框架】    

    🥉与这篇相关的文章:              

    目录

    一、前言

    二、环境搭建

    1、测试搭建

    2、取消打印banner图标

    三、常见功能

    1、QueryWrapper

    2、LambdaQueryWrapper

    三、多条件构建

    1、and 与 or

    2、null判定

    四、查询投影

    1、查询指定字段

    五、聚合查询

    六、分组查询

    七、等值查询

    八、范围查询

    九、模糊查询

    十、排序查询

    十一、映射匹配兼容性


    一、前言

    SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL。

    1. 数据查询语言DQL 数据查询语言DQL基本结构是由SELECT子句,FROM子句,WHERE 子句组成的查询块: SELECT <字段名表> FROM <表或视图名> WHERE <查询条件>

    2 .数据操纵语言DML 数据操纵语言DML主要有三种形式:INSERT、UPDATE、DELETE

    3. 数据定义语言DDL 数据定义语言DDL用来创建数据库中的各种对象——表、视图、索引、同义词、聚簇等如:CREATE TABLE(表) / VIEW (视图 ) / INDEX (索引 ) / SYN (同义词) / CLUSTER (簇)

    注:DDL操作是隐性提交的!不能rollback

    4. 数据控制语言DCL 数据控制语言DCL用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。

    GRANT:授权。

    ROLLBACK [WORK] TO [SAVEPOINT]:回退到某一点。

    ROLLBACK:回滚

    回滚命令使数据库状态回到上次最后提交的状态。

    COMMIT :提交。

    二、环境搭建

    1、测试搭建

    新建一个springboot项目

    pom依赖

    1. <dependencies>
    2.        <dependency>
    3.            <groupId>com.baomidougroupId>
    4.            <artifactId>mybatis-plus-boot-starterartifactId>
    5.            <version>3.4.1version>
    6.        dependency>
    7.        <dependency>
    8.            <groupId>org.springframework.bootgroupId>
    9.            <artifactId>spring-boot-starterartifactId>
    10.        dependency>
    11.        <dependency>
    12.            <groupId>com.alibabagroupId>
    13.            <artifactId>druidartifactId>
    14.            <version>1.1.16version>
    15.        dependency>
    16.        <dependency>
    17.            <groupId>mysqlgroupId>
    18.            <artifactId>mysql-connector-javaartifactId>
    19.            <scope>runtimescope>
    20.        dependency>
    21.        <dependency>
    22.            <groupId>org.springframework.bootgroupId>
    23.            <artifactId>spring-boot-starter-testartifactId>
    24.            <scope>testscope>
    25.        dependency>
    26.        <dependency>
    27.            <groupId>org.projectlombokgroupId>
    28.            <artifactId>lombokartifactId>
    29.            <version>1.18.12version>
    30.        dependency>
    31.    dependencies>

    实体类

    1. //lombok
    2. @Data
    3. @TableName("user")
    4. public class User {
    5.    private Long id;
    6.    private String name;
    7.    @TableField(value = "pwd",select = false)
    8.    private String password;
    9.    private Integer age;
    10.    private String tel;
    11.    @TableField(exist = false)
    12.    private Integer online;
    13. }

    dao层

    1. @Mapper
    2. public interface UserDao extends BaseMapper {
    3. }

    application.yml 文件

    1. # dataSource
    2. spring:
    3. datasource:
    4.   type: com.alibaba.druid.pool.DruidDataSource
    5.   driver-class-name: com.mysql.cj.jdbc.Driver
    6.   url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
    7.   username: root
    8.   password: 123456
    9. main:
    10.   banner-mode: off
    11. # mp日志
    12. mybatis-plus:
    13. configuration:
    14.   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    15. global-config:
    16.   banner: false

    主启动类

    1. @SpringBootApplication
    2. public class Mybatisplus02DqlApplication {
    3.    public static void main(String[] args) {
    4.        SpringApplication.run(Mybatisplus02DqlApplication.class, args);
    5.   }
    6. }

    2、取消打印banner图标

    小知识

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

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

    1. "1.0" encoding="UTF-8"?>
    2. <configuration>
    3. configuration>

    取消MybatisPlus启动banner图标

    application.yml 文件

    1. # mybatis-plus日志控制台输出
    2. mybatis-plus:
    3. configuration:
    4.   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    5. global-config:
    6.   banner: off # 关闭mybatisplus启动图标

    取消SpringBoot的log打印

    application.yml 文件

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

    三、常见功能

    常见功能如下图

    1、QueryWrapper

    1. @Test
    2. void testGetAll(){
    3.   QueryWrapper qw = new QueryWrapper();
    4.   qw.lt("age",18);
    5.   List userList = userDao.selectList(qw);
    6.   System.out.println(userList);
    7. }

    说明:继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取。

    lt: 小于(<) ,最终的sql语句为

    SELECT id,name,password,age,tel FROM user WHERE (age < ?)

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

    QueryWrapper的基础上使用lambda

    1. @Test
    2. void testGetAll(){
    3.   QueryWrapper qw = new QueryWrapper();
    4.   qw.lambda().lt(User::getAge, 10);//添加条件
    5.   List userList = userDao.selectList(qw);
    6.   System.out.println(userList);
    7. }

    User::getAget,为lambda表达式中的,类名::方法名,最终的sql语句为:

    SELECT id,name,password,age,tel FROM user WHERE (age < ?)

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

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

    2、LambdaQueryWrapper

    1. @Test
    2. void testGetAll(){
    3.   LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    4.   lqw.lt(User::getAge, 10);
    5.   List userList = userDao.selectList(lqw);
    6.   System.out.println(userList);
    7. }

    LambdaQueryWrapper :与 QueryWrapper 查询类似,不过使用的是 Lambda 语法。

    三、多条件构建

    1、and 与 or

    上面都是一个条件,那如果有多个条件该如何构建呢?

    需求:查询数据库表中,年龄在10岁到30岁之间的用户信息

    1. @Test
    2. void testGetAll(){
    3.   LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    4.   lqw.lt(User::getAge, 30);
    5.   lqw.gt(User::getAge, 10);
    6.   List userList = userDao.selectList(lqw);
    7.   System.out.println(userList);
    8. }

    gt:大于(>),最终的SQL语句为

    SELECT id,name,password,age,tel FROM user WHERE (age < ? AND age > ?)

    构建多条件的时候,可以支持链式编程

    1. LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    2. lqw.lt(User::getAge, 30).gt(User::getAge, 10);
    3. List userList = userDao.selectList(lqw);
    4. System.out.println(userList);

    需求:查询数据库表中,年龄小于10或年龄大于30的数据

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {
    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    9.        lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
    10.        List userList = userDao.selectList(lqw);
    11.        System.out.println(userList);
    12.   }
    13. }

    or()就相当于我们sql语句中的or关键字,不加默认是and,最终的sql语句为:

    SELECT id,name,password,age,tel FROM user WHERE (age < ? OR age > ?)

    2、null判定

    1. //模拟页面传递过来的查询数据
    2. UserQuery uq = new UserQuery();
    3. uq.setAge(10);
    4. uq.setAge2(30);
    5. //null判定
    6. LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    7. lqw.lt(User::getAge, uq.getAge2());
    8. if( null != uq.getAge()) {
    9.   lqw.gt(User::getAge, uq.getAge());
    10. }
    11. List userList = userDao.selectList(lqw);
    12. System.out.println(userList);

    四、查询投影

    1、查询指定字段

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

    1. void testGetAll(){
    2.   LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    3.   lqw.select(User::getId,User::getName,User::getAge);
    4.   List userList = userDao.selectList(lqw);
    5.   System.out.println(userList);
    6. }

    select(...)方法用来设置查询的字段列,可以设置多个,最终的sql语句为:

    SELECT id,name,age FROM user

    如果使用的不是lambda,就需要手动指定字段

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {
    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        QueryWrapper lqw = new QueryWrapper();
    9.        lqw.select("id","name","age","tel");
    10.        List userList = userDao.selectList(lqw);
    11.        System.out.println(userList);
    12.   }
    13. }

    最终的sql语句为:SELECT id,name,age,tel FROM user

    五、聚合查询

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

    count:总记录数、max:最大值、min:最小值、avg:平均值、sum:求和

    1. @Autowired
    2.    private UserDao userDao;
    3.    
    4.    @Test
    5.    void testGetAll(){
    6.        QueryWrapper lqw = new QueryWrapper();
    7.        
    8.        // 计数
    9.        //lqw.select("count(*) as count");
    10.        //SELECT count(*) as count FROM user
    11.        
    12.        // 最大值
    13.        //lqw.select("max(age) as maxAge");
    14.        //SELECT max(age) as maxAge FROM user
    15.        
    16.        // 最小值
    17.        //lqw.select("min(age) as minAge");
    18.        //SELECT min(age) as minAge FROM user
    19.        
    20.        // 求和
    21.        //lqw.select("sum(age) as sumAge");
    22.        //SELECT sum(age) as sumAge FROM user
    23.        
    24.        // 平均值
    25.        lqw.select("avg(age) as avgAge");
    26.        //SELECT avg(age) as avgAge FROM user
    27.        
    28.        List> userList = userDao.selectMaps(lqw);
    29.        System.out.println(userList);
    30.   }

    六、分组查询

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {
    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        QueryWrapper lqw = new QueryWrapper();
    9.        lqw.select("count(*) as count,tel");
    10.        lqw.groupBy("tel");
    11.        List> list = userDao.selectMaps(lqw);
    12.        System.out.println(list);
    13.   }
    14. }

    groupBy为分组,最终的sql语句为

    SELECT count(*) as count,tel FROM user GROUP BY tel

    注意:聚合与分组查询,无法使用lambda表达式来完成

    MP只是对MyBatis的增强,如果MP实现不了,我们可以直接在DAO接口中使用MyBatis的方式实现

    查询条件

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

    MP的查询条件有很多:范围匹配(> 、 = 、between)、模糊匹配(like)、空判定(null)、包含性匹配(in)、分组(group)、排序(order)

    七、等值查询

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {
    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    9.        lqw.eq(User::getName, "Jerry").eq(User::getPassword, "jerry");
    10.        User loginUser = userDao.selectOne(lqw);
    11.        System.out.println(loginUser);
    12.   }
    13. }

    eq(): 相当于 =,对应的sql语句为

    SELECT id,name,password,age,tel FROM user WHERE (name = ? AND password = ?)

    selectList:查询结果为多个或者单个

    selectOne:查询结果为单个

    八、范围查询

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {
    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    9.        lqw.between(User::getAge, 10, 30);
    10.        //SELECT id,name,password,age,tel FROM user WHERE (age BETWEEN ? AND ?)
    11.        List userList = userDao.selectList(lqw);
    12.        System.out.println(userList);
    13.   }
    14. }

    gt():大于(>)、ge():大于等于(>=)、lt():小于(<)、lte():小于等于(<=)、between():between ? and ?

    九、模糊查询

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {
    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        LambdaQueryWrapper lqw = new LambdaQueryWrapper();
    9.        lqw.likeLeft(User::getName, "J");
    10.        //SELECT id,name,password,age,tel FROM user WHERE (name LIKE ?)
    11.        List userList = userDao.selectList(lqw);
    12.        System.out.println(userList);
    13.   }
    14. }

    like():前后加百分号,如 %xxx%、likeLeft():前面加百分号,如 %xxx、likeRight():后面加百分号,如 xxx%

    十、排序查询

    1. @SpringBootTest
    2. class Mybatisplus02DqlApplicationTests {
    3.    @Autowired
    4.    private UserDao userDao;
    5.    
    6.    @Test
    7.    void testGetAll(){
    8.        LambdaQueryWrapper lwq = new LambdaQueryWrapper<>();
    9.        /**
    10.         * condition :条件,返回boolean,
    11.         当condition为true,进行排序,如果为false,则不排序
    12.         * isAsc:是否为升序,true为升序,false为降序
    13.         * columns:需要操作的列
    14.         */
    15.        lwq.orderBy(true,false, User::getId);
    16.        userDao.selectList(lw);
    17.        System.out.println(lwq);
    18.   }
    19. }

    orderBy排序

    condition:条件,true则添加排序,false则不添加排序

    isAsc:是否为升序,true升序,false降序

    columns:排序字段,可以有多个

    orderByAsc/Desc(单个column):按照指定字段进行升序/降序

    orderByAsc/Desc(多个column):按照多个字段进行升序/降序

    orderByAsc/Desc

    condition:条件,true添加排序,false不添加排序

    多个columns:按照多个字段进行排序

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

    十一、映射匹配兼容性

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

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

    那么问题就来了:

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

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

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

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

    当模型类中多了一个数据库表不存在的字段,就会导致生成的sql语句中在select的时候查询了数据库不存在的字段,程序运行就会报错。

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

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

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

    知识点1:@TableField

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

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

    该问题主要是表的名称和模型类的名称不一致,导致查询失败。

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

    知识点2:@TableName

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

    代码演示

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

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

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

    1. @Data
    2. @TableName("tbl_user")
    3. public class User {
    4.    private Long id;
    5.    private String name;
    6.    private String password;
    7.    private Integer age;
    8.    private String tel;
    9. }

    步骤3:将字段password修改成pwd

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

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

    1. @Data
    2. @TableName("tbl_user")
    3. public class User {
    4.    private Long id;
    5.    private String name;
    6.    @TableField(value="pwd")
    7.    private String password;
    8.    private Integer age;
    9.    private String tel;
    10. }

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

    1. @Data
    2. @TableName("tbl_user")
    3. public class User {
    4.    private Long id;
    5.    private String name;
    6.    @TableField(value="pwd")
    7.    private String password;
    8.    private Integer age;
    9.    private String tel;
    10.    private Integer online;
    11. }

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

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

    1. @Data
    2. @TableName("tbl_user")
    3. public class User {
    4.    private Long id;
    5.    private String name;
    6.    @TableField(value="pwd")
    7.    private String password;
    8.    private Integer age;
    9.    private String tel;
    10.    @TableField(exist=false)
    11.    private Integer online;
    12. }

    步骤7:查询时将pwd隐藏

    1. @Data
    2. @TableName("tbl_user")
    3. public class User {
    4.    private Long id;
    5.    private String name;
    6.    @TableField(value="pwd",select=false)
    7.    private String password;
    8.    private Integer age;
    9.    private String tel;
    10.    @TableField(exist=false)
    11.    private Integer online;
    12. }

    不积跬步无以至千里,趁年轻,使劲拼,给未来的自己一个交代!向着明天更好的自己前进吧!

  • 相关阅读:
    5步快速了解电商渠道数字化管理||电商API数据采集|数据分析
    RocketMQ 5.0 API 与 SDK 的演进
    基于SqlSugar的开发框架循序渐进介绍(27)-- 基于MongoDB的数据库操作整合
    随着量子计算的崭露头角,C 语言在未来是否需要做出适应性的改变,以适应新的计算架构和算法?
    工程水文学复习资料
    Python unittest单元测试框架 TestSuite测试套件
    【JVM技术专题】Thread的stackSize与-Xss参数的区别「分析篇」
    什么是js的闭包,它是如何产生的
    第三章:使用Vue脚手架
    吴恩达深度学习笔记——结构化机器学习项目(Structuring Machine Learning Projects)
  • 原文地址:https://blog.csdn.net/aasd23/article/details/127813469