Mybatis-Plus ! 这篇足以!!

什么是Mybatis-Puls

MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

MyBatis-Puls与Mybatis 是最好的搭档的关系。

Mybatis-Plus ! 这篇足以!!

Mybatis-Puls的特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作,BaseMapper

  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求,以后简单的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 操作智能分析阻断,也可自定义拦截规则,预防误操作

Mybatis 与Mpuls的异同

这里的Mpuls是指Mybatis-puls

相同点

  • 对底层JDBC进行高度封装:Mybatis与Mybatis-puls 都是简化我们连接数据库开发,尽可能地减少使用JDBC操作封装

不同点

  • 降低代码解耦性:Mybatis 使用接口与xml进行配置绑定,解除强耦合,Mybatis-Puls实现BaseMapper

    接口 直接调用封装好的底层增删改查语句

  • 实现方法不同:Mybatis还是使用xml实现sql语句增删改查, Mybatis-Puls 使用BaseMapper

    进行sql语句的继承调用

  • 自动生成代码器不同:Mybatis 是使用mybatis逆向工程生成pojo,接口 已经模板代码   Mybatis-Puls 是使用代码生成器自动生成代码

Mybatis-Puls增删改查

  • 简单增删改查–单一表 – 使用继承BaseMapper接口

    封装好的增删改查方法

  • 复杂增删改查 -多表或复杂语句操作  — 使用条件构造器语法实现

Mybatis-Puls 快速入门

快速入门Mybatis-puls步骤

环境准备

  • 1.创建数据库

  • 2.导入maven依赖

  • 3.配置数据源连接信息

增删改查准备

  • 4.创建pojo类

  • 5.创建mapper接口 继承基本的接口BaseMapper接口

  • 6.启动类 添加扫描mapper注解

开始使用Mybatis-puls

创建数据库和表

-- 创建user表
CREATE TABLE user
(
    id BIGINT(20NOT NULL COMMENT '主键ID',
    name VARCHAR(30NULL DEFAULT NULL COMMENT '姓名',
    age INT(11NULL DEFAULT NULL COMMENT '年龄',
    email VARCHAR(50NULL DEFAULT NULL COMMENT '邮箱',
    PRIMARY KEY (id)
);

INSERT INTO USER (idNAME, age, email) VALUES
(1'Jone'18'test1@baomidou.com'),
(2'Jack'20'test2@baomidou.com'),
(3'Tom'28'test3@baomidou.com'),
(4'Sandy'21'test4@baomidou.com'),
(5'Billie'24'test5@baomidou.com');

-- 真实开发中,version(乐观锁)、delete(逻辑删除)、gmt_create、gmt_modified

创建springboot项目

引入maven依赖

在springboot项目依赖基础上 映入相关依赖

<!-- 数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>
<!-- mybatis-plus --> 
<!-- mybatis-plus 是自己开发,并非官方的! -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.0</version>
</dependency>

配置数据源连接信息

# mysql 5 驱动不同 com.mysql.jdbc.Driver

# mysql 8 驱动不同com.mysql.cj.jdbc.Driver、需要增加时区的配置 serverTimezone=GMT%2B8
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus? useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root 
spring.datasource.password=123456 

增删改查准备

创建pojo封装类

@Data     //get set 方法
@AllArgsConstructor  //有参构造
@NoArgsConstructor  //无参构造
public class User {

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

Mapper接口

继承基本的接口BaseMapper接口,调用BaseMapper提前封装好的sql语句,实现自动增删改查

@Mapper
//在对应的Mapper 上面继承基本类BaseMapper
//将数据库封装对象的参数,传递到BaseMapper这个泛型类中,作为参数 就可以激活BaseMapper这个类 使用泛型先封装好的增删改查方法
public interface UserMapper extends BaseMapper<User{
      //直接可以使用mybatis-puls 的增删改查方法
      //所有的CRUD操作都已经编写完成了
      //你不需要像以前的配置一大堆文件了

    /**
     * 原理
     * 将数据库封装对象作为参数,传递到BaseMapper这个泛型类中,
     * 就可以激活BaseMapper这个类 使用泛型先封装好的增删改查方法
      */


}

mapper接口省去简单增删改查方法的创建的原因

实现BaseMapper这个接口

  • 接口里面使用泛型,已经提前构造好了简单的增删改查方法 传递参数对象 给泛型接收即可

  • 将数据库封装对象的参数,传递到BaseMapper这个泛型类中,作为参数 就可以激活BaseMapper这个类 使用泛型先封装好的增删改查方法

以下是BaseMapper源码

(这是mapper省略增删改查的原因 ,不用出现在项目中)

//传进去的对象  将由泛型接收  变成使用的增删改查方法
/**
 * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
 * 这个 Mapper 支持 id 泛型*/

public interface BaseMapper<T{
     /**
     * 插入一条记录
     * @param var1(对象)
     * 实体对象
     * @return int
     */

    //插入一条记录 传入是一个对象
    int insert(T var1);
     /**
     * 根据 ID 删除
     * @param id
     * 主键ID
     * @return int
     */

    //根据Id删除记录 传入是一个id
    int deleteById(Serializable var1);


    /**
     * 根据 columnMap 条件,删除记录 var1对象
     * @param columnMap
     * 表字段 map 对象
     * @return int
     */

    //根据对象参数,删除含参数的map对象
    int deleteByMap(@Param("cm") Map<String, Object> var1);

    /**
     * 根据 entity(对象) 条件,删除记录  var1 对象
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return int
     */

    //根据对象条件,删除表记录  
    int delete(@Param("ew") Wrapper<T> var1);

    /**
     * 删除(根据ID 批量删除)
     * @param idList
     * 主键ID列表
     * @return int
     */

    //根据主键id删除表记录
    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> var1);

    /**
     * 根据 ID 修改
     * @param var1
     * 实体对象
     * @return int
     */

    //根据Id 更新修改表记录
    int updateById(@Param("et") T var1);

    /**
     * 根据 whereEntity 条件,更新记录
     * @param entity
     * 实体对象
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return
     */

    //根据对象 更新表记录
    int update(@Param("et") T var1, @Param("ew") Wrapper<T> var2);

    /**
     * 根据 ID 查询
     * @param id
     * 主键ID
     * @return T
     */

    //根据主键Id查询表记录
    T selectById(Serializable var1);

    /**
     * 查询(根据ID 批量查询)
     * @param idList
     * 主键ID列表
     * @return List<T>
     */

    //根据主键id 进行记录批量查询
    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> var1);

    /**
     * 查询(根据 columnMap 条件)
     * @param columnMap
     * 表字段 map 对象
     * @return List<T>
     */

    //根据对象条件 ,查询整个表的map集合记录
    List<T> selectByMap(@Param("cm") Map<String, Object> var1);

    /**
     * 根据 entity 条件,查询一条记录
     * @param entity
     * 实体对象
     * @return T
     */

    //根据对象条件 ,查询记录
    T selectOne(@Param("ew") Wrapper<T> var1);

    /**
     * 根据 Wrapper 条件,查询总记录数
     * @param wrapper
     * 实体对象
     * @return int
     */


    Integer selectCount(@Param("ew") Wrapper<T> var1);

    /**
     * 根据 entity 条件,查询全部记录
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<T>
     */
 
    List<T> selectList(@Param("ew") Wrapper<T> var1);

    /**
     * 根据 Wrapper 条件,查询全部记录
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<T>
     */

    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> var1);

     /**
     * 根据 Wrapper 条件,查询全部记录
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<Object>
     */

    List<Object> selectObjs(@Param("ew") Wrapper<T> var1);

    /** 
     * 用法:(new RowBounds(offset, limit), ew);
     * 根据 entity 条件,查询全部记录(并翻页)
     * @param rowBounds
     * 分页查询条件(可以为 RowBounds.DEFAULT)
     * @param wrapper
     * 实体对象封装操作类(可以为 null)
     * @return List<T>
     */

    //分页查询
    IPage<T> selectPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);

    /** -- 不常用,
     * 根据 Wrapper 条件,查询全部记录(并翻页)
     * @param rowBounds
     * 分页查询条件(可以为 RowBounds.DEFAULT)
     * @param wrapper
     * 实体对象封装操作类
     * @return List<Map<String, Object>>
     */

    IPage<Map<String, Object>> selectMapsPage(IPage<T> var1, @Param("ew") Wrapper<T> var2);
}

启动类

启动类添加mapper扫描注解 使用加载mapper使用

package com.lhw.mybatispuls;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages = "com.lhw.mybatispuls.dao.UserMapper")
public class MybatisPulsApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPulsApplication.class, args);
    }

}

调用增删改查

前面的mapper接口已经封装了具体的增删改查方法

这里我们可以直接调用传值进去,进行简单的增删改查就可以直接使用

一般使用的范围模块

  • 测试模块使用 — 测试检查,传值并直接调用增删改查的方法

  • 业务层使用 –实现业务,传值并直接调用增删改查的方法

测试类调用增删改查

调用封装好的增删改查的方法

使用注入的接口调用其继承父类的增删改查方法,我们只需要传入相应查询的值即可

@SpringBootTest
class MybatisPulsApplicationTests {

    //继承了BaseMapper 所有的方法都来着父类
    //我们也可以编写自己的扩展方法
    @Autowired  //注入doa层接口即可
    private UserMapper userMapper;

    @Test
    void contextLoads() {
        //参数是一个Wrapper  是一个条件构造器 启用就使用条件查询 ,不启用就null 不使用条件查询
        //如何调用继承的增删改查的方法:使用注入的接口调用其继承父类的方法,我们只需要传值即可
        List<User> users = userMapper.selectList(null);
        //打印结果值
        users.forEach(System.out::println);
    }

}

配置日志

将sql可视化

配置mybatis-puls或mybatis配置

#配置日志
#使用默认控制台输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

简单增删改查操作

mybatis-puls的增删改查都交由mybatis-puls的特殊接口 BaseMapper提前定义完毕,只需要传入值,并调用相应的增删改查方法即可

插入数据

基本插入数据操作

@Test
public void testInsert()
{
        User user = new User();
        user.setName("张三");
        user.setAge(23);
        user.setEmail("123456789@qq.com");

        //插入数据
        int insert = userMapper1.insert(user);  //帮我们自动生成id
        //打印插入数据结果
        System.out.println(insert);  //受影响行数
        System.out.println(user);   //发现 id会自动回填  主键生成策略

    }

这里了解一下什么是主键生成策略

主键生成策略

数据库插入的id默认值为:生成全局唯一id

雪花算法

生成全局唯一id

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!

想要生成的id自增

  • pojo实体类字段上@TableId(type = IdType.AUTO)

  • 数据库设置主键自增

查看注解源码

public enum IdType {
    AUTO(0),    //数据库id自增
    NONE(1),    //未设置主键
    INPUT(2),    //手动输入
    ASSIGN_ID(3),    //默认的全局唯一id
    ASSIGN_UUID(4),    //全局唯一id UUID
    ID_WORKER_STR(5); //ID_WORKER 字符串表示法
}

例如

在实体类声明id自增

@Data     //get set 方法
@AllArgsConstructor  //有参构造
@NoArgsConstructor  //无参构造
public class User {

    //在实体类 声明id全局自增
    @TableId(type = IdType.AUTO) //声明id自增
    private Long id;
    private String name;
    private Integer age;
    private String email;

}

删除数据

基本删除操作

//测试删除
@Test
public void testDeleteById()
{
    userMapper.deleteById(1L);
}

//通过id批量删除
@Test
public void testDeleteBatchId()
{
    userMapper.deleteBatchIds(Arrays.asList(234));
}

//通过map删除
@Test
public void testDeleteMap()
{
    HashMap<String, Object> map = new HashMap<>();
    map.put("name""陈伟");
    userMapper.deleteByMap(map);
}

逻辑删除

  • 物理删除:从数据库中直接移除

  • 逻辑删除:在数据库中没有移除,而是通过一个变量让他失效,deleted = 0 变成  deleted=1

使用步骤

  • 在数据库中增加一个deleted字段

  • 在实体类中增加属性

  • 配置逻辑删除变量

  • 调用逻辑删除

在数据库中增加一个deleted字段

在实体类中增加属性

@TableLogic     //逻辑删除
private Integer deleted;

配置逻辑删除变量

在配置文件里 添加两个逻辑删除变量

#配置逻辑删除
#delete-value=1 是启用逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
#not-delete-value=0 是关闭逻辑删除
mybatis-plus.global-config.db-config.logic-not-delete-value=0

调用逻辑删除

//测试删除
@Test
public void testDeleteById(){
    userMapper.deleteById(1L);
}

更新数据

更新数据

//测试更新
@Test
public void testUpdate()
{
    User user = new User();
    //通过条件自动拼接动态SQL
    user.setId(5L);
    user.setName("陈伟");
    user.setAge(20);
    user.setEmail("1277077741@qq.com");
    //注意:updateById 参数是一个对象!
    int i = userMapper.updateById(user);
    System.out.println(i);
}

自动插入

需要自动更新的东西,比如字段插入时间

创建时间、修改时间!这些个操作都是自动化完成的,我们不希望手动更新!

阿里巴巴开发手册:所有的数据库表:gmt_create、gmr_modified、几乎所有的表都要配置上!而且需要自动化

代码级别实现

实体类的字段属性上需要增加注解

@Data     //get set 方法
@AllArgsConstructor  //有参构造
@NoArgsConstructor  //无参构造
public class User {

    private Long id;
    private  String name;
    private Integer age;
    private String email;

    //字段添加自动填充内容 例如时间戳
    //创建时间时,自动填写一个插入时间戳操作
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    //更新时间时,自动填写一个更新时间戳操作
    @TableField(fill = FieldFill.UPDATE)
    private Date updateTime;

}

创建一个自动插入处理器

编写处理器处理注解即可!

@Component  //一定不要忘记把处理器加到IOC容器中
@Slf4j      //打印一下日志之类的
public class MyMetaObjectHandler implements MetaObjectHandler {
    //插入时候的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ......");
        //default MetaObjectHandler
        //setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) 
        //自动插入时间
        //将需要处理的字段 以参数的形式放入处理器
        this.setFieldValByName("createTime"new Date(), metaObject);
        this.setFieldValByName("updateTime"new Date(), metaObject);
    }

    //更新时候的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ......");
        //自动更新时间
        //将需要处理的字段 以参数的形式放入处理器
        this.setUpdateFieldValByName("updateTime"new Date(), metaObject);
    }
}

4、测试插入

5、测试更新、观察时间即可!

乐观锁

乐观锁的作用:在多线程下,插队操作是否会被拦截

原子引用!

乐观锁:顾名思义十分乐观,他总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,再次更新值测试!

悲观锁:顾名思义十分悲观,他总是任务总是出现问题,无论干什么都会上锁!再去操作!

我们这里主要讲解,乐观锁机制!

乐观锁实现方式:

  • 取出记录,获取当前version

  • 更新时,带上这个version

  • 执行更新时,set version = new version where version = oldversion

  • 如果version不对,就更新失败

    乐观锁:1、先查询,获得版本号 version = 1
    — A
    update user set name = “ChanV”, version = version + 1
    where id = 2 and version = 1

    — B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
    update user set name = “ChanV”, version = version + 1
    where id = 2 and version = 1

乐观锁的实现

  • 在数据库添加version字段

  • 在实体类中添加对应version字段和注解

  • 注册乐观锁拦截器

1、给数据库中增加version字段!

2、我们实体类加对应的字段和乐观锁注解

@Data     //get set 方法
@AllArgsConstructor  //有参构造
@NoArgsConstructor  //无参构造
public class User {

    private Long id;
    private  String name;
    private Integer age;
    private String email;

   //在实体类添加对应字段 和乐观锁注解
    @Version    //乐观锁version注解
   private Integer version;

}

注册乐观锁拦截器

实现一个配置类 将需要配置的乐观锁拦截器配置进去

//扫描我们的mapper文件夹
@MapperScan("com.lhw.mapper")
@EnableTransactionManagement
@Configuration  //配置类
public class MyBatisPlusConfig {
    //注册乐观锁插件
    //配置乐观锁的插件 形成一个乐观锁的拦截器 当版本不对时,更新失败
    @Bean
    public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
        return new OptimisticLockerInnerInterceptor();
    }
}

测试乐观锁的使用

在多线程下,插队操作是否会被拦截

    //测试乐观锁成功!执行成功就会执行更新操作
    @Test
    public void testOptimisticLocker(){
        //1、查询用户信息
        User user = userMapper.selectById(1330080433207046145L);
        //2、修改用户信息
        user.setName("ChanV");
        user.setEmail("1277077741@qq.com");
        //3、执行更新操作  执行成功就会执行更新操作
        userMapper.updateById(user);
    }

    //测试乐观锁失败!多线程下  就不会执行更新操作 拦截上锁
    @Test
    public void testOptimisticLocker2(){
        //线程1
        User user = userMapper.selectById(5L);
        user.setName("ChanV111");
        user.setEmail("1277077741@qq.com");
        //模拟另一个线程执行了插队操作
        User user2 = userMapper.selectById(5L);
        user2.setName("ChanV222");
        user2.setEmail("1277077741@qq.com");
        userMapper.updateById(user2);

        //自旋锁多次尝试提交
        userMapper.updateById(user);    //如果没有乐观锁就会覆盖队线程的值
    }
}

查询数据

基本查询

    //查询测试
    @Test
    public void testSelectById()
{
        User user = userMapper.selectById(1L);
        System.out.println(user);
    } 
    //批量查询
    @Test
    public void testSelectByBatchId()
{
        //批量查询方法selectBatchIds()接收一个对象
        List<User> users = userMapper.selectBatchIds(Arrays.asList(123));
        users.forEach(System.out::println);
    }

    //条件查询 map
    @Test
    public void testSelectByBatchIds()
{
        //使用map 存储键值对
        HashMap<String, Object> map = new HashMap<>();
        //自定义要查询
        map.put("name""张三");
        map.put("age",3);

        //查询结果使用list集合接收结果
        List<User> users = userMapper.selectByMap(map);
        //打印结果
        users.forEach(System.out::println);

    }

分页查询

分页在网站使用的十分之多!

  • 1、原始的 limit 进行分页

  • 2、pageHelper 第三方插件

  • 3、MP其实也内置了分页插件

Mybatis-Puls内置分页插件的使用

1、配置拦截器组件即可

//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    return paginationInterceptor;
}

2、直接使用Page对象即可!

    //测试分页查询
    @Test
    public void testPage(){
        //参数一:当前页
        //参数二:页面大小
        //使用了分页插件之后,所有的分页操作也变得简单了!
        Page<User> page = new Page<>(25);
        userMapper.selectPage(page, null);
        page.getRecords().forEach(System.out::println);
        System.out.println(page.getTotal());
    }
}

条件构造器

十分重要:Wapper(条件构造器)

我们写复杂的SQL语句时,可以使用条件构造器的语法代替来进行替换

条件构造器语法

条件判断

allEq:所有条件全等于

allEq({id:1,name:"老王",age:null})--->id = 1 and name = '老王' and age is null
allEq({id:1,name:"老王",age:null}, false)--->id = 1 and name = '老王'

eq: 等于 =

eq("name", "老王")--->name = '老王'

ne:不等于 < >

ne("name""老王")--->name <> '老王'

gt: 大于 >

gt("age"18)--->age > 18

ge:大于等于  >=

ge("age"18)--->age >= 18

le:小于等于 < =

le("age"18)`--->`age <= 18

It:小于 <

lt("age"18)--->age < 18

区间

between:介于什么之间

between("age"1830)`--->`age between 18 and 30

like:LIKE ‘%值%

左右都包含

like("name""王")--->name like '%王%    //左右都能匹配到'王' 字

likeLeft:LIKE ‘%王’

左包含  只能向左匹配

likeLeft("name""王")--->name like '%王'

likeRight  :LIKE ‘王%’

右包含  只能向右匹配

likeRight("name""王")`--->`name like '王%'

notlike:NOT LIKE ‘%值%

左右都不包含

notLike("name""王")`--->`name not like '%王%'

in:在范围内

in("age",{1,2,3})`--->`age in (1,2,3)  //对象的值不在这个范围内

notIn:不在范围内

notIn("age",{1,2,3})`--->`age not in (1,2,3)  //对象的值 不在这个范围

非空

isNull

空值

isNull("name")--->name is null //是空值

isNotNull

非空

isNotNull("name")--->name is not null  //不为空 非空

排序

orderByAsc

排序:ORDER BY 字段, … ASC   //字段升序

orderByAsc("id""name")--->order by id ASC,name ASC

orderByDesc

排序:ORDER BY 字段, … DESC     //字段降序

orderByDesc("id""name")`--->`order by id DESC,name DESC  //降序

orderBy

排序:ORDER BY 字段, …    //默认排序

orderBy(truetrue"id""name")`--->`order by id ASC,name ASC

条件查询实例

不为空查询

  @Test
    public void QueryWrapper(){
        //查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于12岁
        QueryWrapper<User> wrapper = new QueryWrapper<>();  //查询条件构造器
        //调用查询构造器的查询方法
        wrapper.
                isNotNull("name")  //不为空
                .isNotNull("email"//条件不为空
                .ge("age",12);  //对象大于等于
        userMapper.selectList(wrapper).forEach(System.out::println);  //调用条件构造器进行查询 并打印
    }

相等查询

 @Test
    public void Test2()
{
        //查询名字是否相等
        QueryWrapper<User> wrapper = new QueryWrapper<>(); //获取条件构造器对象
        wrapper.eq("name","张三");  //查询数据库是否
        User user = userMapper.selectOne(wrapper);  //查询一个数据,出现过多结果使用list 或Map集合
        System.out.println(user);
    }

区间查询

 @Test
    public void Test3()
{
        //查询在年龄在20~30之间的用户
        QueryWrapper<User> wrapper = new QueryWrapper<>();  //获取条件构造器对象
        wrapper.between("age",20,30); //区级查询
        Integer count = userMapper.selectCount(wrapper);  //查询结果
        System.out.println(count);
    }

模糊查询

//模糊查询
@Test
void test4(){
    //查询年龄在19到30岁之间的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //左和右
    wrapper.notLike("name""b")  //在name 字段中不包含 b
            .likeRight("email""t"); //在email字段 中 向右包含t
    List<Map<StringObject>> maps = userMapper.selectMaps(wrapper);
    maps.forEach(System.out::println);
}

子查询

@Test
void test5(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //id 在子查询中查出来
    wrapper.inSql("id""select id from user where id < 3");
    List<Object> objects = userMapper.selectObjs(wrapper);
    objects.forEach(System.out::println);
}

排序查询

@Test
void test6(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //通过id进行排序
    wrapper.orderByDesc("id");   //通过id 进行降序排序
    //wrapper.orderByASC("id");  //通过id 进行升序排序
    List<User> users = userMapper.selectList(wrapper);
    users.forEach(System.out::println);
}

代码自动生成器

创建使用代码生成器模板类

public class Code {
    public static void main(String[] args{
        //需要构建一个 代码自动生成器 对象
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        //配置策略
        //1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");  //获取用户目录
        gc.setOutputDir(projectPath + "/src/main/java");  //保存路径
        gc.setAuthor("ChanV");  //声明作者名称
        gc.setOpen(false);  //是否打开资源浏览器
        gc.setFileOverride(false);  //是否覆盖
        gc.setServiceName("%sService"); //去Service的I前缀
        gc.setIdType(IdType.ID_WORKER);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);   //是否生成
        mpg.setGlobalConfig(gc);

        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");  //设置连接URL
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");  //设置数据源名称
        dsc.setUsername("root");      //设置数据库用户名
        dsc.setPassword("root");    //设置数据库密码
        dsc.setDbType(DbType.MYSQL);  //设置连接的数据库类型
        mpg.setDataSource(dsc);       //连接数据源

        //3、包的配置
        PackageConfig pc = new PackageConfig();  //获取包配置对象
        pc.setModuleName("blog");        //设置模块名
        pc.setParent("com.chanv");      //设置包路径
        pc.setEntity("pojo");            //设置实体类名
        pc.setMapper("mapper");            //设置Mapper名
        pc.setService("service");        //设置Service名
        pc.setController("controller");  //设置controller名
        mpg.setPackageInfo(pc);          //设置包信息对象

        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();

        //strategy.setInclude("user");    //设置要映射的表名  生成其他的表 只需要改这个
        strategy.setInclude("user","student","teacher");  //引入多个参数,直接上传多张表

        strategy.setNaming(NamingStrategy.underline_to_camel);  //设置包名命名规则
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);  //设置数据库字段命名规则
        strategy.setEntityLombokModel(true);           //自动lombok
        strategy.setLogicDeleteFieldName("deleted");   //设置逻辑删除

        //自动填充配置
        TableFill createTime = new TableFill("create_time", FieldFill.INSERT);
        TableFill updateTime = new TableFill("update_time", FieldFill.UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(createTime);  //创建时间 自动填充字段
        tableFills.add(updateTime);  //更新时间 自动填充字段
        strategy.setTableFillList(tableFills);

        //乐观锁
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);     //控制层映射地址 localhost:8080/hello_id_2
        mpg.setStrategy(strategy);

        mpg.execute();  //执行代码构造器
    }
}


原文始发于微信公众号(理想Talk):Mybatis-Plus ! 这篇足以!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/27841.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!