1、特性
 
 无侵入 
 :只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑  
 
 
 损耗小 
 :启动即会自动注入基本 
  CURD 
 ,性能基本无损耗,直接面向对象操作  
 
 
 强大的 
  CRUD  
 操作 
 :内置通用 
  Mapper 
 、通用 
  Service 
 ,仅仅通过少量配置即可实现单表大  
 
 
 部分 
  CRUD  
 操作,更有强大的条件构造器,满足各类使用需求  
 
 
 支持 
  Lambda  
 形式调用 
 :通过 
  Lambda  
 表达式,方便的编写各类查询条件,无需再担心字  
 
 
 段写错  
 
 
 支持主键自动生成 
 :支持多达 
  4  
 种主键策略(内含分布式唯一 
  ID  
 生成器 
  - Sequence 
 ),可  
 
 
 自由配置,完美解决主键问题  
 
 
 支持 
  ActiveRecord  
 模式 
 :支持 
  ActiveRecord  
 形式调用,实体类只需继承 
  Model  
 类即可进  
 
 
 行强大的 
  CRUD  
 操作  
 
 
 支持自定义全局通用操作 
 :支持全局通用方法注入( 
  Write once, use anywhere  
 )  
 
 
 内置代码生成器 
 :采用代码或者 
  Maven  
 插件可快速生成 
  Mapper  
 、 
  Model  
 、 
  Service  
 、  
 
 
 Controller  
 层代码,支持模板引擎,更有超多自定义配置等您来使用  
 
 
 内置分页插件 
 :基于 
  MyBatis  
 物理分页,开发者无需关心具体操作,配置好插件之后,写分  
 
 
 页等同于普通 
  List  
 查询  
 
 
 分页插件支持多种数据库 
 :支持 
  MySQL 
 、 
 MariaDB 
 、 
 Oracle 
 、 
 DB2 
 、 
 H2 
 、 
 HSQL 
 、  
 
 
 SQLite 
 、 
 Postgre 
 、 
 SQLServer  
 等多种数据库  
 
 
  内置性能分析插件 
  :可输出 
   SQL  
  语句以及其执行时间,建议开发测试时启用该功能,能快  
 
 
  
  速揪出慢查询  
 
 
  
  内置全局拦截插件 
  :提供全表 
   delete  
  、 
   update  
  操作智能分析阻断,也可自定义拦截规  
 
 
  
  则,预防误操作 
 
 
2、操作
1、创建一个User用户表用于测试

# Host: localhost  (Version 5.7.23-log)
# Date: 2023-12-10 14:21:50
# Generator: MySQL-Front 6.0  (Build 2.20)
#
# Structure for table "tb_user"
#
CREATE TABLE `tb_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(20) DEFAULT NULL COMMENT '用户名',
  `password` varchar(32) DEFAULT NULL COMMENT '密码',
  `role` varchar(10) DEFAULT NULL COMMENT '角色:0:管理员  1:普通用户',
  `sex` int(11) DEFAULT NULL COMMENT '性别,0:女 1:男',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `createTime` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
#
# Data for table "tb_user"
#
INSERT INTO `tb_user` VALUES (1,'admin','123456','0',1,25,'2022-10-23 00:12:36'),(6,'张曼玉','123456','1',1,18,'2022-10-23 00:12:44'),(14,'a3','122','1',1,313,'2023-10-17 21:31:48'),(15,'aaa','123456','1',1,111,'2023-11-13 20:26:10'),(17,'aaa','weqe','1',0,NULL,'2023-11-20 18:33:09');
2、新建maven工程

3、导入依赖

<dependencies>
    <!-- MyBatisPlus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.2</version>
    </dependency>
   
    <!-- MySql -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.30</version>
    </dependency>
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.24</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3307/mybatis?
useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
4、配置application.properties
 
 
5、插件lombok下载
 
 
 
 Lombok 
 提供的常用注解:  
 
 
 @Getter/@Setter  
 :用在类或属性上,用在类上可以作用于这个类的所有属性,写在属性 上只作用于属性名,再也不用自己手写setter 
 和 
 getter 
 方法了  
 
 
 @ToString  
 :用在类上,可以自动覆写 
 toString 
 方法,当然还可以加其他参数,例如  
 
 
 @ToString(exclude=”id”) 
 排除 
 id 
 属性,或者 
 @ToString(callSuper=true, includeFieldNames=true)调用父类的 
 toString 
 方法,包含所有属  
 
 
 @EqualsAndHashCode  
 :用在类上,自动生成 
 equals 
 方法和 
 hashCode 
 方法  
 
 
 @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor  
 :用 在类上,自动生成无参构造和使用所有参数的构造函数以及把所有@NonNull 
 属性作为参数的构造函数  
 
 
 @RequiredArgsConstructor  
 主要是对当前类中带有 
 final  
 的属性进行属性注入  
 
 
 @Data  
 :注解在类上,相当于同时使用了  
 @ToString  
 、  
 @EqualsAndHashCode  
 、  
 
 
 @Getter  
 、  
 @Setter  
 和  
 @RequiredArgsConstrutor  
 这些注解,对于  
 POJO 
 类  
 十分有用  
 
 
 @Value  
 :用在类上,是 
 @Data 
 的不可变形式,相当于为属性添加 
 final 
 声明,只提供 
 getter方法,而不提供setter 
 方法  
 
 
 @Slf4j  
 : 自动创建 
 Slf4j 
 日志对象 
 log 
 ,用于记录系统日志信息 
 
6、创建实体类

package com.cqh.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data //@Data : 注解在类上,提供类的get、set、equals、hashCode、canEqual、toString、无参构造方法,没有有参构造方法。
@AllArgsConstructor // 全部参数构造方法
@NoArgsConstructor //无参数构造方法
@TableName("tb_user")
public class User {
    @TableId
    private int id;
    private String username;
    private String password;
    private String role;
    private int sex;
    private int age;
    @TableField(value = "createTime")
    private Date createTime;
}
7、创建userMapper接口

8、完善启动类
 
 为了能够让 
 SpringBoot 
 扫描并且识别此组件,我们需要在 
 SpringBoot 
 启动类上开启 
 Mapper 
 接口  
 
 
 扫描功能,添加 
 @MapperScan() 
 注解  
 
 
 
package com.cqh;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.cqh.mapper")
@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        SpringApplication.run(Main.class,args);
    }
}9、测试
查询所有

 
 
package com.cqh;
import com.cqh.entity.User;
import com.cqh.mapper.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;
//查询全部用户
//此方法需要我们传递Wrapper对象,此对象是条件构造器,我们现在要查询全部用户先不用,所以传null即可
    @Test
    public void test01(){
        List<User> users = userMapper.selectList(null);
        for (User user : users) {
            System.out.println("user = " + user);
        }
    }
}
为了方便查看配置日志

# 配置日志
mybatis-plus.configuration.logimpl=org.apache.ibatis.logging.stdout.StdOutImpl
添加user
//插入数据
    @Test
    public void test02(){
        User user1 = new User();
        user1.setUsername("xiaoMin");
        user1.setPassword("123456");
        user1.setAge(11);
        user1.setRole("0");
        user1.setSex(1);
        int insert = userMapper.insert(user1);
        System.out.println("insert = " + insert);
    }
 删除功能
 删除功能
 
 
 BaseMapper 
 中提供了 
 5 
 个删除方法 
 
 
 //用于删除数据库中的记录。它接受一个类型为 
 
 
 
Serializable 的参数 
 id,表示要删除的记录的唯一标识符。 
 
 
 
 
根据Map删除对应数据
 
 
//根据map删除
    @Test
    public void deleteTest(){
        Map<String,Object> map = new HashMap<>();
        map.put("username","xiaoMin");
        map.put("age",11);
        int num = userMapper.deleteByMap(map);
        System.out.println(num);
    }根据多个id进行批量删除

 
 
//根据多个id进行批量删除
    @Test
    public void deleteTest2(){
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(15);
        ids.add(17);
        int num = userMapper.deleteBatchIds(ids);
        System.out.println(num);
    } 
 
 多条件删除
 
 //根据多个条件进行删除
    @Test
    public void deleteTest3(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username","a3");
        userQueryWrapper.eq("sex",1);
        int num = userMapper.delete(userQueryWrapper);
        System.out.println(num);
    }
修改功能
修改方法BaseMapper中提供了两个


根据id修改

 
 
    //根据id修改
    @Test
    public void updateTest(){
        User user = new User();
        user.setId(6);
        user.setUsername("李四");
        int num = userMapper.updateById(user);
        System.out.println(num);
    }查询功能
 
 下图中的两个方法,分别是通过单个 
 id 
 查询数据,和 
 id 
 集合来查询数据, 
 

此方法为根据Map中传递的条件进行查询
 
 
 //根据Map中传递的条件进行查询
    @Test
    public void selectTest(){
        Map<String,Object> map = new HashMap<>();
        map.put("id",6);
        map.put("username","李四");
        List<User> users = userMapper.selectByMap(map);
        users.forEach(user -> System.out.println(user));
    }此方法Wrapper条件构造器传递参数为null表示查询全部数据

 
 注意:所有的CRUD方法中只要涉及到Wrapper条件构造器的如果不需要使用都可以传入为  
 
 
 null,但是要注意一般查询可以传入,但是修改和删除一般不可以,因为如果删除和修改没有条  
 
 
 件会导致影响全部数据  
 
新增功能
//插入数据
    @Test
    public void test02(){
        User user1 = new User();
        user1.setUsername("xiaoMin");
        user1.setPassword("123456");
        user1.setAge(11);
        user1.setRole("0");
        user1.setSex(1);
        int insert = userMapper.insert(user1);
        System.out.println("insert = " + insert);
    }
有一个问题就是没有主键返回
 
 
 
 其实这里 
 MyBatis-Plus 
 是通过雪花算法来进行自动生成的 
 id 
 ,但是要 
 注意: 
 我们的主键必须叫  
 
 
 id,并且必须是包装类型,否则不生效 
 
 
 
 常见主键生成策略 
 
 
  数据库自增长序列或字段:最常见的方式。利用数据库,全数据库唯一。  
 
 
  
  UUID 
  :常见的方式。可以利用数据库也可以利用程序生成,一般来说全球唯一。  
 
 
  
  Redis 
  生成 
  ID 
  :当使用数据库来生成 
  ID 
  性能不够要求的时候,我们可以尝试使用 
  Redis 
  来生成ID。这主要依赖于 
  Redis 
  是单线程的,所以也可以用生成全局唯一的 
  ID 
  。  
 
 
  
  Twitter 
  的 
  snowflake( 
  雪花 
  ) 
  算法: 
  snowflake 
  是 
  Twitter 
  开源的分布式 
  ID 
  生成算法,结果是一个long 
  型的 
  ID 
  。  
 
 
  
  zookeeper 
  生成唯一 
  ID 
  : 
  zookeeper 
  主要通过其 
  znode 
  数据版本来生成序列号,可以生成 
  32位和64 
  位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号。  
 
 
  
   雪花算法  
  
 
   
   snowflake 
   是 
   Twitter 
   开源的分布式 
   ID 
   生成算法,结果是一个 
   long 
   型的 
   ID 
   。  
  
 
   
   其核心思想是:使用 
   41bit 
   作为毫秒数, 
   10bit 
   作为机器的 
   ID 
   ( 
   5 
   个 
   bit 
   是数据中心, 
   5 
   个 
   bit 
   的机器  
  
 
   
   ID 
   ), 
   12bit 
   作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 
    4096  
   个 
    ID 
   ),最后还有  
  
 
   
   一个符号位,永远是 
   0 
  
 
   
   
   其中 
   MyBatis-Plus 
   中提供的一个注解 
   @TableId  
  
 
   
 
   
 
 
(注意:表一定要是主键自增 )
修改User实体类

 现在主键返回了
自定义CRUD
 
 MyBatis-Plus 
 的 
 BaseMapper 
 本身提供了很多通用的 
 CRUD 
 方法,但是由于我们的业务问题有的  
 
 
 时候必须要自定义一些方法 
 
 
  MyBatis-Plus 
  是在 
  MyBatis 
  的基础之上只做增强不做修改的即可,所以如果想要实  
 
 
  
  现自定义的方法,具体操作其实和 
  MyBatis 
  没有什么区别  
 
 
 配置
 
   如果我们需要进行复杂映射就可能会涉及到映射文件 
   mapper.xml 
   那么这个文件位置的配置,我  
  
 
   
   们可以在 
   properties 
   配置文件中进行配置 
  
 
  # 指定mapper文件位置
mybatis-plus.mapper-locations = classpath*:/mapper/**/*.xml
测试
注解方式
编写mapper

package com.cqh.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cqh.entity.User;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface UserMapper extends BaseMapper<User> {
    /**
     * 根据name查询数据
     * @param username
     * @return
     */
    @Select("select * from tb_user where username=#{username}")
    List<User> selectByName(String username);
}
编写测试方法

xml方式

 
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cqh.mapper.UserMapper">
    <select id="selectByName" resultType="com.cqh.entity.User">
        select * from tb_user where username=#{username}
    </select>
</mapper> 测试一下
IService接口
 
 通用 
  Service CRUD  
 封装 
 IService (opens new window) 
 接口,进一步封装 
  CRUD  
 采用  
 get 查询单行 remove  
 删除  
 list  
 查询集合  
 page  
 分页  
 前缀命名方式区分  
 Mapper  
 层避免混  
 
 
 淆, 
 
 
  泛型  
  T  
  为任意实体对象  
 
 
  
  建议如果存在自定义通用 
   Service  
  方法的可能,请创建自己的  
  IBaseService  
  继承  
 
 
  
  Mybatis 
  - 
  Plus  
  提供的基类  
 
 
  
  对象  
  Wrapper  
  为 条件构造器 
 
 
  
  使用参考: 
  MybatisPlus入门-CSDN博客 
 
 
 分页插件
 
  Page: 
  该类继承了  
  IPage  
  类,实现了  
  简 单 分 页 模 型  
  如果你要实现自己的分页模型可以继承  
 
 
  
  Page  
  类或者实现  
  IPage  
  类 
 
 
 创建config开启分页

package com.cqh.config;
/**
 * @author cqh
 * @date 2023/12/10
 * @Description
 */
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//开启扫描,注意包名不要写错(有了MyBatisPlus的配置类,我们就可以把所有的相关配置都写在这里)
@MapperScan("com.qf.mybatisplusdemo.mapper")
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new
                MybatisPlusInterceptor();
//分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new
                PaginationInnerInterceptor(DbType.MYSQL));
        return mybatisPlusInterceptor;
    }
}分页测试
 
 
 
    @Test
    public void PaginationInnerInterceptorTest(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
        Page<User> page = new Page<>(1,3);
//条件构造器Wrapper目前没有就写null
        userMapper.selectPage(page,null);
    }Page对象常用方法
@Test
    public void PaginationInnerInterceptorTest2(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
        Page<User> page = new Page<>(2,3);
//条件构造器Wrapper目前没有就写null
        userMapper.selectPage(page,null);
//获取记录
        List<User> users = page.getRecords();
        users.forEach(user -> System.out.println(user));
        System.out.println(page.getPages()); //获取总页数
        System.out.println(page.getTotal()); //获取总数据量
        System.out.println(page.hasNext());//是否有下一页
        System.out.println(page.hasPrevious());//是否有上一页
    }

逻辑删除
 
 在企业中对于删除,一般情况下是不会真正的把数据删除掉的,而是会进行 逻辑删除  
 
 
 所以大家会发现一些系统,管理员可以看到已经删除的用户信息,实际上这就是一种逻辑删除,  
 
 
 也就是根据数据表中的类似于: 
 deleted 
 的属性来标记用户删除,而并非真正删除。  
 
 
 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。 
 
 
 就是将删除delete语句改成了修改语句一般是专门一个字段用来做为是否被删除的判断 
 
 
 
条件构造器
 
 MyBatis-Plus 
 提供了强大的条件构造器。通过条件构造器可以写一些复杂的 
 SQL 
 语句,从而提高  
 
 
 开发效率。  
 
 
 查询 
 mybatisPlus 
 源码可以看到,条件构造器 
 wrapper 
 继承情况  
 
 
 Wrapper 
 :条件构造器,最顶端的一个类  
 
 
         AbstractWrapper:用于 
 sql 
 语句条件的封装,主要是封装 
 where 
 条件  
 
 
                 QueryWrapper:查询条件封装(一般删除的条件也使用QueryWrapper 
 )  
 
 
                 UpdateWrapper:更新条件封装  
 
 
                  AbstractLambdaWrapper:具有Lambda 
  语法的条件封装  
 
 
  
                          LambdaQueryWrapper:具有Lambda语法查询条件封装  
 
 
  
                          LambdaUpdateWrapper:具有Lambda语法更新条件封装  
 
 
 
 所有的条件使用方法,在官网中有很详细的介绍  
 
 
 具体地址: 
 https://www.baomidou.com/pages/10c804/#abstractwrapper  
 
QueryWrapper
我这里 查询username不为空的用户,并且年龄大于10岁
比较用的.ge() 这是大于等于

还有许多比较方法

// 查询名字为chen的用户

 
 
// 查询年龄18~25岁之间的用户
 
 
// 查询年龄大于等于25岁的用户

// 模糊查询:查询名字不包含a的用户,反之like就是包含
 
 
//模糊查询:包含左侧或者右侧具体内容

子查询
 lambda表达式执行条件
 lambda表达式执行条件 
 
 
 
 在 
 QueryWrapper 
 中有 
 and 
 或者 
 or 
 这样的方法,要注意的是默认都是通过 
 and 
 来进行连接条件,  
 
 
 但是如果主动调用 
 or 
 方法,将会改变,还有一点如果 
 and 
 或者 
 or 
 表达式时中出现 
 lambda 
 表达式,  
 
 
 将会改变条件的优先级,先来执行 
 lambda 
 表达式的条件  
 
 
 
condition
 
 我们在写项目的时候,所有的条件都是由用户进行传递的,那么有的时候就无法避免参数出现空  
 
 
 值 
 null 
 的情况,所以我们应该要做一些判断,其实很多方法都提供了 
 boolean condition 
 这个参  
 
 
 数,表示该条件 
 是否 
 加入最后生成的 
 sql 
 中,也就是可以通过它来进行判断  
 
 
 QueryWrapper执行修改和删除操作
 QueryWrapper执行修改和删除操作
 
 
//修改用户id为24的username为jack

 
 
 
 
UpdateWrapper
 
 继承自  
 AbstractWrapper 
  , 
 自身的内部属性  
 entity  
 也用于生成 
  where  
 条件  
 
 
 可以通过 
 set 
 方法来进行修改  
 
 
 
//修改年龄大于等于10,并且username为xiao的用户role为 0
 

LambdaQueryWrapper&LambdaUpdateWrapper
 
 它们两个的主要目的是为了防止我们在编写的时候,字段名称编写错误,我们可以直接通过  
 
 
 Lambda 
 的方式来直接获取指定字段对应的实体类对应的名称  
 
 
 LambdaQueryWrapper  
 查询 
 
 
 
 
 LambdaUpdateWrapper  
 修改 
 
 
//修改年龄大于10,并且name为xiao的用户role为 1

  我的所有测试代码 
 
package com.cqh;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cqh.entity.User;
import com.cqh.mapper.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
    @Autowired
    private UserMapper userMapper;
//查询全部
    @Test
    public void test01(){
        List<User> users = userMapper.selectList(null);
        for (User user : users) {
            System.out.println("user = " + user);
        }
    }
//插入数据
    @Test
    public void test02(){
        User user1 = new User();
        user1.setUsername("chen1");
        user1.setPassword("123456");
        user1.setAge(18);
        user1.setRole("1");
        user1.setSex(1);
        int insert = userMapper.insert(user1);
        System.out.println("insert = " + insert);
        System.out.println("id = " + user1.getId());
    }
    //根据map删除
    @Test
    public void deleteTest(){
        Map<String,Object> map = new HashMap<>();
        map.put("username","xiaoMin");
        map.put("age",11);
        int num = userMapper.deleteByMap(map);
        System.out.println(num);
    }
//根据多个id进行批量删除
    @Test
    public void deleteTest2(){
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(15);
        ids.add(17);
        int num = userMapper.deleteBatchIds(ids);
        System.out.println(num);
    }
    //根据多个条件进行删除
    @Test
    public void deleteTest3(){
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username","a3");
        userQueryWrapper.eq("sex",1);
        int num = userMapper.delete(userQueryWrapper);
        System.out.println(num);
    }
    //根据id修改
    @Test
    public void updateTest(){
        User user = new User();
        user.setId(6);
        user.setUsername("李四");
        int num = userMapper.updateById(user);
        System.out.println(num);
    }
    //根据Map中传递的条件进行查询
    @Test
    public void selectTest(){
        Map<String,Object> map = new HashMap<>();
        map.put("id",6);
        map.put("username","李四");
        List<User> users = userMapper.selectByMap(map);
        users.forEach(user -> System.out.println(user));
    }
    @Test
    public void selectByNameTest(){
        List<User> users = userMapper.selectByName("李四");
        users.forEach(user -> System.out.println(user));
    }
    @Test
    public void PaginationInnerInterceptorTest(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
        Page<User> page = new Page<>(1,3);
//条件构造器Wrapper目前没有就写null
        userMapper.selectPage(page,null);
    }
    @Test
    public void PaginationInnerInterceptorTest2(){
//简单分页模型 current:第几页 size:显示几条数据
//底层逻辑就是使用Limit分页的公式 (index-1)*pageSize
        Page<User> page = new Page<>(2,3);
//条件构造器Wrapper目前没有就写null
        userMapper.selectPage(page,null);
//获取记录
        List<User> users = page.getRecords();
        users.forEach(user -> System.out.println(user));
        System.out.println(page.getPages()); //获取总页数
        System.out.println(page.getTotal()); //获取总数据量
        System.out.println(page.hasNext());//是否有下一页
        System.out.println(page.hasPrevious());//是否有上一页
    }
    // 查询username不为空的用户,并且年龄大于10岁
    @Test
  public void selectTest1(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("username")
                .ge("age",10);
        userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
    }
    // 查询名字为chen的用户
    @Test
   public void selectTest2(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username","chen");
        User user = userMapper.selectOne(wrapper);//类似于map传入条件
        System.out.println(user);
    }
    // 查询年龄18~25岁之间的用户
    @Test
   public void selectTest3(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age",18,25);
        userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
    }
    // 查询年龄大于等于25岁的用户
    @Test
   public void selectTest4(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.ge("age",25);
        userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
    }
    // 模糊查询:查询名字不包含a的用户,反之like就是包含
    @Test
   public void selectTest5(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.notLike("username","a");
        userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
    }
    //模糊查询:包含左侧或者右侧具体内容
    @Test
   public void selectTest6(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
    // 模糊查询:查询名字不包含qf的用户,反之like就是包含
    // likeLeft和likeRight
    // 左右就是 %在左或者在右
    // 以下就是 a% 相当于以a开头的名字
        wrapper.likeRight("username","a");
        userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
    }
    //通过子查询,查询id等于6的用户信息,此方法也可以进行表关联查询
    @Test
   public void selectTest7(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id","select id from tb_user where id=6");
        userMapper.selectObjs(wrapper).forEach(System.out::println);
    }
    // 查询用户名中包含a并且年龄大于29或者crateTime为空的用户
    @Test
   public void selectTest8(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like("username","a")
                .and(w->w.gt("age",26).or().isNull("createTime"));
        userMapper.selectList(wrapper).forEach(System.out::println);
    }
    // 模糊查询:查询名字包含a的用户,并且按照age升序排序,注意参数不能为空
    @Test
   public void selectTest9(){
    //假设用户传递参数
        String username = "a";
        Integer age = 1;
        //先判断条件是否符合,符合才会组合到SQL语句中
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(username),"username",username)
                .orderByAsc(age != null,"age");
        userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
    }
    //修改用户id为24的username为jack
    @Test
   public void updateTest1(){
       // QueryWrapper<User> wrapper = new QueryWrapper<>();
       // wrapper.eq("id",24);
        User user = new User();
        user.setUsername("jack");
       // userMapper.update(user,wrapper);
        userMapper.update(user,new QueryWrapper<User>().eq("id",24));
    }
    //删除username为jack的用户
    @Test
   public void deleteTest1(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username","jack");
        userMapper.delete(wrapper);
    }
    //修改年龄大于10,并且username为xiao的用户role为 0
    @Test
   public void updateTest2(){
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.gt("age",10)
                .eq("username","xiao")
                .set("role","0");
//无需传递user对象,直接赋值为null
        userMapper.update(null,wrapper);
    }
    @Test
   public void selectTest10(){
//假设用户传递参数
        String username = "a";
        Integer age = null;
//LambdaQueryWrapper就是为了防止我们写错字段,可以直接通过Lambda的方式来直接获取指定字段对应的实体类对应的名称
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(username),User::getUsername,username)
                .orderByAsc(age != null,User::getAge);
        userMapper.selectList(wrapper).forEach(System.out::println);//类似于map传入条件
    }
    //修改年龄大于10,并且name为xiao的用户role为 1
    @Test
   public void updateTest3(){
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.gt(User::getAge,10)
                .eq(User::getUsername,"xiao")
                .set(User::getRole,"1");
//无需传递user对象,直接赋值为null
        userMapper.update(null,wrapper);
    }
}



















