MyBatis-Plus DQL与其他知识点

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

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

🥈 系列专栏: 【Java框架】    

🥉与这篇相关的文章:              

Springboot 整合与文件配置Springboot 整合与文件配置_程序猿追的博客-CSDN博客
springboot 项目起步讲解及自动装配原理springboot 项目起步讲解及自动装配原理_程序猿追的博客-CSDN博客
MyBatis-Plus介绍与项目起步讲解MyBatis-Plus介绍与项目起步讲解_程序猿追的博客-CSDN博客

目录

一、前言

二、环境搭建

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依赖

<dependencies>
​
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
​
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
​
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
​
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
​
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
​
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
​
    </dependencies>

实体类

//lombok
@Data
@TableName("user")
public class User {
    private Long id;
    private String name;
    @TableField(value = "pwd",select = false)
    private String password;
    private Integer age;
    private String tel;
    @TableField(exist = false)
    private Integer online;
}

dao层

@Mapper
public interface UserDao extends BaseMapper<User> {
}

application.yml 文件

# dataSource
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
    username: root
    password: 123456
  main:
    banner-mode: off
# mp日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    banner: false

主启动类

@SpringBootApplication
public class Mybatisplus02DqlApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(Mybatisplus02DqlApplication.class, args);
    }
​
}

2、取消打印banner图标

小知识

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

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

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>

取消MybatisPlus启动banner图标

application.yml 文件

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

取消SpringBoot的log打印

application.yml 文件

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

三、常见功能

常见功能如下图

1、QueryWrapper

@Test
void testGetAll(){
    QueryWrapper qw = new QueryWrapper();
    qw.lt("age",18);
    List<User> userList = userDao.selectList(qw);
    System.out.println(userList);
}

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

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

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

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

QueryWrapper的基础上使用lambda

@Test
void testGetAll(){
    QueryWrapper<User> qw = new QueryWrapper<User>();
    qw.lambda().lt(User::getAge, 10);//添加条件
    List<User> userList = userDao.selectList(qw);
    System.out.println(userList);
}

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

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

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

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

2、LambdaQueryWrapper

@Test
void testGetAll(){
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.lt(User::getAge, 10);
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
}

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

三、多条件构建

1、and 与 or

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

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

@Test
void testGetAll(){
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.lt(User::getAge, 30);
    lqw.gt(User::getAge, 10);
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
}

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

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

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

LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 30).gt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
​
    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }
}

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

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

2、null判定

//模拟页面传递过来的查询数据
UserQuery uq = new UserQuery();
uq.setAge(10);
uq.setAge2(30);
​
//null判定
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, uq.getAge2());
if( null != uq.getAge()) {
    lqw.gt(User::getAge, uq.getAge());
}
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);

四、查询投影

1、查询指定字段

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

void testGetAll(){
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    lqw.select(User::getId,User::getName,User::getAge);
    List<User> userList = userDao.selectList(lqw);
    System.out.println(userList);
}

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

SELECT id,name,age FROM user

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
​
    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        QueryWrapper<User> lqw = new QueryWrapper<User>();
        lqw.select("id","name","age","tel");
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }
}

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

五、聚合查询

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

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

@Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        QueryWrapper<User> lqw = new QueryWrapper<User>();
        
        // 计数
        //lqw.select("count(*) as count");
        //SELECT count(*) as count FROM user
        
        // 最大值
        //lqw.select("max(age) as maxAge");
        //SELECT max(age) as maxAge FROM user
        
        // 最小值
        //lqw.select("min(age) as minAge");
        //SELECT min(age) as minAge FROM user
        
        // 求和
        //lqw.select("sum(age) as sumAge");
        //SELECT sum(age) as sumAge FROM user
        
        // 平均值
        lqw.select("avg(age) as avgAge");
        //SELECT avg(age) as avgAge FROM user
        
        List<Map<String, Object>> userList = userDao.selectMaps(lqw);
        System.out.println(userList);
    }

六、分组查询

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
​
    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        QueryWrapper<User> lqw = new QueryWrapper<User>();
        lqw.select("count(*) as count,tel");
        lqw.groupBy("tel");
        List<Map<String, Object>> list = userDao.selectMaps(lqw);
        System.out.println(list);
    }
}

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)

七、等值查询

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
​
    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.eq(User::getName, "Jerry").eq(User::getPassword, "jerry");
        User loginUser = userDao.selectOne(lqw);
        System.out.println(loginUser);
    }
}

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

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

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

selectOne:查询结果为单个

八、范围查询

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
​
    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.between(User::getAge, 10, 30);
        //SELECT id,name,password,age,tel FROM user WHERE (age BETWEEN ? AND ?)
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }
}

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

九、模糊查询

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
​
    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.likeLeft(User::getName, "J");
        //SELECT id,name,password,age,tel FROM user WHERE (name LIKE ?)
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);
    }
}

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

十、排序查询

@SpringBootTest
class Mybatisplus02DqlApplicationTests {
​
    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll(){
        LambdaQueryWrapper<User> lwq = new LambdaQueryWrapper<>();
        /**
         * condition :条件,返回boolean,
                当condition为true,进行排序,如果为false,则不排序
         * isAsc:是否为升序,true为升序,false为降序
         * columns:需要操作的列
         */
        lwq.orderBy(true,false, User::getId);
​
        userDao.selectList(lw);
        System.out.println(lwq);
    }
}

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注解

@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
}

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

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

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

@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    @TableField(value="pwd")
    private String password;
    private Integer age;
    private String tel;
}

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

@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    @TableField(value="pwd")
    private String password;
    private Integer age;
    private String tel;
    private Integer online;
}

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

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

@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    @TableField(value="pwd")
    private String password;
    private Integer age;
    private String tel;
    @TableField(exist=false)
    private Integer online;
}

步骤7:查询时将pwd隐藏

@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    @TableField(value="pwd",select=false)
    private String password;
    private Integer age;
    private String tel;
    @TableField(exist=false)
    private Integer online;
}

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

  • 57
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 46
    评论
评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿追

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值