MybatisPlus一键解决增删改查,直接写Controller类

1,116 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

1.介绍

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

(是国人写的,所以源码的注释也是中文的)

MyBatis Plus特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

支持的数据库:

  • mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird
  • Phoenix 、clickhouse 、Sybase ASE 、 OceanBase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库 、

2.样例

<!--MyBatis Plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>

image.png

目录结构:

image.png

model类

/**
 * @Author: sc
 * @Date: 2022/8/27 14:51
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")
public class User {

    @TableId(type = IdType.AUTO)
    private Integer id;

    private String username;

    private String nickname;

    private String password;
}

model类中有不需要的字段可以:

image.png

@TableField(select = false)    //查询时,则不返回该字段的值
@TableField(value = "email")    //通过tableField进行字段不一致的映射
@TableField(exist = false)  //设置该字段在数据库表中不存在

Mapper类:

/**
 * @Author: sc
 * @Date: 2022/8/27 14:51
 */
@Mapper
public interface UserMapper extends BaseMapper<User> {

}

Service类:

/**
 * @Author: sc
 * @Date: 2022/8/27 14:51
 */
public interface UserService extends IService<User> {
}

Impl类:

/**
 * @Author: sc
 * @Date: 2022/8/27 14:51
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

Controller类:

/**
 * @Author: sc
 * @Date: 2022/8/27 14:52
 */
@RestController
@RequestMapping(value = "/api/user")
public class UserController {

    @Resource
    private UserService userService;

    /***
     * 增加user
     */
    @PostMapping("/saveUser")
    public String add(@RequestBody User user) {
        // 增加user
        userService.save(user);
        return "ok";
    }

}

可以看到提供了很多方法:

image.png

apifox测试成功!

image.png

数据库:

image.png

3.详解主键id

image.png

image.png

主键生成策略

AUTO数据库ID自增
NONE无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUTinsert前自行set主键值
ASSIGN_ID分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
ASSIGN_UUID分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法)
ID_WORKER分布式全局唯一ID 长整型类型(please use ASSIGN_ID) ,已过时
UUID32位UUID字符串(please use ASSIGN_UUID) ,已过时
ID_WORKER_STR分布式全局唯一ID 字符串类型(please use ASSIGN_ID) ,已过时

如果你是自增主键,那和第二点一样,如果你是雪花算法

MybatisPlus (3.3.1)的主键策略默认是雪花算法,如果不显式设置主键的话, MybatisPlus 通过代码自动通过雪花算法算出一个值,插入的时候就会将其作为id插入。

雪花算法( SnowFlake )是一个 Long 类型的 Java 长整型数字,一般对应 MySQL 中的类型为 **BIGINT(20)** ;具有趋势单调递增,且全局唯一的特点。

记住是BIGINT(20),要不然会精度丢失报错

image.png

image.png

image.png

4.queryWrapper妙用


/***
 * 测试
 */
@PostMapping("/testUser")
public String test(@RequestBody User user) {

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    // name <> 's' (不相等)
    queryWrapper.ne("username", "s");
    queryWrapper.ne(true,"username", "s");
    
    // username = 's'
    queryWrapper.eq(true, "username", "s");
    queryWrapper.eq("username", "s");

    // age > 18
    queryWrapper.gt("age", 18);
    queryWrapper.gt(true,"age", 18);

    // age >= 18
    queryWrapper.ge("age", 18);
    queryWrapper.ge(true, "age", 18);

    // age < 18
    queryWrapper.lt("age", 18);
    queryWrapper.le(true, "age", 18);

    // age <= 18
    queryWrapper.le("age", 18);
    queryWrapper.le(true, "age", 18);

    // between 18 and 20
    queryWrapper.between("age", 18, 20);

    // age not between 18 and 20
    queryWrapper.notBetween("age", 18, 20);

    queryWrapper.likeLeft(true, "username", "s");
    queryWrapper.likeRight("username", "s");

    queryWrapper.likeLeft(true, "username", "s");
    queryWrapper.likeLeft("username", "s");

    queryWrapper.like(true, "username", "s");
    queryWrapper.like("username", "s");

    return "ok";
}

分页查询:

image.png

还要配置pageInterceptor

(可以单独加一个@Configure类,就不用每次都写拦截器了)

image.png