首页 > 其他分享 >Mybatis Plus保姆级教程 (一学就会!!!)

Mybatis Plus保姆级教程 (一学就会!!!)

时间:2024-11-18 20:47:16浏览次数:3  
标签:一学 private id Plus user Mybatis new 查询 主键

目录

一、概述

二、框架结构

2.1 框架剖析

2.2 基本使用

2.2.1 创建 Mapper 接口

2.2.2 测试

三、常用注解

3.1 @TableName

3.2 @TableField

3.2.1 exist

3.2.2 select

3.2.3 fill

3.3 @TableId

3.3.1 value

3.3.2 type

NONE

INPUT​​​​​​​

AUTO

ASSIGN_ID 和 ASSIGN_UUID

3.4 @Version

3.5 @EnumValue

3.6 @TableLogic

四、关于查询

4.1 selectList()

4.2 selectById()

4.3 selectBatchIds()

4.4 selectByMap()

4.5 selectCount()

4.5 selectMaps()

4.6 selectPage()

4.7 selectMapsPage()

4.8 自定义SQL(多表关联查询)

五、关于添加

六、关于删除

6.1 deleteBatchIds()

6.2 delete()

6.3 deleteByMap()

七、关于修改

7.1 update()

八、自动生成

8.1 导入依赖​​​​​​​

8.2 Main方法

九、总结


一、概述

这个Mybatis Plus(以下简称MP)是什么东西呢?

Mybatis相信很多小伙伴都用过,是目前市面上非常火的ORM框架。而MP则是一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生。最重要的一点,它是国产的(骄傲)。

官网:https://mp.baomidou.com/guide/

在官网中我能可以看到MP的愿景是:

成为 MyBatis 最好的搭档,就像魂斗罗中的 1P、2P,基友搭配,效率翻倍。

图片

它有以下特性:

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

  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

可以看到真的非常强大。

由于它是对Mybatis的增强,所以只要Mybatis能支持的数据库,它都支持。

二、框架结构

图片

以上内容均来自官网。

2.1 框架剖析

废话不多说,好不好用,用起来看看!

1.创建工程

图片

选择上图中的几个组件,这里我们不需要再选择Mybatis Framework了。

直接创建

图片

等待依赖下载完毕。

2.添加Mybatis Plus的依赖

<dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.3.1.tmp</version>
</dependency>

3.支持的数据库类型

依赖下载完后可以看到一共导入了五个Jar包

图片

在mybatis-plus-annotation:3.3.1.tmp这个jar包中

图片

我们能看到它所支持的数据库类型

图片

4.自动配置

在mybatis-plus-boot-starter:3.3.1.tmp这个jar包中

图片

这个配置文件相信大家肯定已经很熟悉了,要想在Spring Boot中开箱即用,肯定需要被Spring Boot自动配置。

spring.factories

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration,\
  com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration

可以看到我们的Mybatis Plus会自动装载两个类。

MybatisPlusAutoConfiguration.class

图片

  • @Configuration注解声明它是一个配置类。

  • @ConditionalOnClass这个条件注解告诉Spring容器里面得有SqlSessionFactory.class, SqlSessionFactoryBean.class这两个类,才会加载MybatisPlusAutoConfiguration.class这个类。

  • 这里还有一个很有意思的注解:@AutoConfigureAfter。这个注解什么意思呢?就是在加载配置的类之后再加载当前类。意思必须先加载DataSourceAutoConfiguration.class这个类,才会加载MybatisPlusAutoConfiguration.class这个类。

DataSourceAutoConfiguration.class

图片

可以看到它也是一个配置类。它这里使用@EnableConfigurationProperties注解为当前类注入属性,从DataSourceProperties.class这个类中。

DataSourceProperties.class

图片

@ConfigurationProperties这个注解表示我们会从配置文件里面,前缀是spring.datasource这个的配置项中读取属性值。读取属性值后,加载到当前类中,给成员变量赋值。

可以看到这个类中都是一些比较熟悉的属性:url、username、password等等。这些属性的值就从配置文件里面前缀是spring.datasource的配置项中来。

所以现在我们可以来给配置文件添加一些简单的配置项。

application.yml​​​​​​​

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mp_test_db?useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456

现在这几个配置项就会填充到DataSourceProperties.class类的对应属性中了。

这样我们Spring Boot中集成的Mybatis就可以和数据库连接了。

数据库不会安装的小伙伴们可参考

MYSQL 学习指南 (看完这篇就够了,万字收藏!!!)_mysql入门教程-CSDN博客

2.2 基本使用

注意:集成mybatis-plus要把mybatis、mybatis-spring去掉,避免冲突。

我们先在 mp_test_db 库中创建一张表 user。

SET NAMES utf8mb4;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int NOT NULL auto_increment COMMENT '主键id',
  `name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '姓名',
  `age` int NOT NULL COMMENT '年龄',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic;

插入几条测试数据​​​​​​​

INSERT into user(name, age) values('张三', 32);
INSERT into user(name, age) values('李四', 18);
INSERT into user(name, age) values('王五', 23);

创建实体类​​​​​​​


@Data
public class User {
    /**
     * 主键id
     */
    private Long id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
}

2.2.1 创建 Mapper 接口

这个用过Mybatis的小伙伴应该都很清楚哈,这里我不再细说什么是 Mapper 接口了。

这里和Mybatis有所不同的是,你只需要创建接口即可,并不需要创建具体的实现类。有点类似 Spring Data JPA,一样的套路。

这里我们只需要继承MP的父接口 BaseMapper 即可。​​​​​​​


public interface UserMapper extends BaseMapper<User> {
    
}

写完 Mapper 接口,别忘了在主启动类上加上

@MapperScan("com.age.mybatisplus.mapper")

否则一会工程启动时候,会找不到 Mapper。

2.2.2 测试​​​​​​​

mport org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

@SpringBootTest
class UserMapperTest {

    @Resource
    private UserMapper userMapper;

    @Test
    void test() {
        // 不加条件,查询user表所有的数据
        userMapper.selectList(null).forEach(System.out::println);
    }
}

图片

图片

它这里帮我们把一些增删改查的接口,全都写好了,让我们可以更加愉快的crud!

在上面的控制台日志中可以看到并没有打印SQL语句,其实我们可以设置的,在application.yml中添加

mybatis-plus:
    configuration:
       log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

这一段配置,日志里面就可以打印SQL语句了。

以上就是Mybatis Plus的基本使用。

三、常用注解

其实我们现在开发的话呢,其实都比较少使用xml文件了,很多时候都是通过注解的方式。

我们可以看些MP常用的注解都有哪些,以及怎么使用。

3.1 @TableName

作用:用来映射数据库的表名。

刚才上面的例子中我们可以看到,为什么MP会准确找到user这张表进行查询?是不是就是因为我们创建的实体类,名字就叫User,所以可以和数据库中的user表对应起来的关系。

那假如现在我的实例类名称换成Student,看下什么效果

图片

它就会提示我Table 'mp_test_db.student' doesn't exist。

那么有时候我的实体类名称不一定和数据库中的表名能完全对应上,这时候@TableName注解就派上用场了。

我们可以在Student实体类加上这个注解​​​​​​​

@Data
@TableName(value = "user")
public class Student {

图片

现在又会是查询user这张表了。

3.2 @TableField

@TableName注解是把实体类和表做映射,那么表里面还有字段信息,类属性和表字段肯定也是一一映射的。

如果类属性和表字段无法一一对应时,假如我将 ”name“ 这个属性修改为 ”userName“

图片

这时候我们只需要@TableField注解的 value 属性即可解决​​​​​​​

/**
 * 姓名
 */
@TableField(value = "name")
private String userName;

除了value属性之外,还有两个我们需要关注的属性。

3.2.1 exist

当我们的实体类中定义了一些数据库中不存在的字段时​​​​​​​

/**
 * 外号
 * 数据库不存在的字段
 */
private String nickname;

调用一下查询接口

图片

发现会报错:Unknown column 'nickname' in 'field list'。

遇到这种情况怎么办?我们只需要设置一下exist属性即可解决​​​​​​

/**
 * 外号
 * 数据库不存在的字段
 */
@TableField(exist = false)
private String nickname;

再运行一下

图片

现在没问题了。

3.2.2 select

该属性表示是否查询该字段。​​​​​​​

/**
 * 年龄
 */
@TableField(select = false)
private Integer age;

图片

SQL语句中就不再查询age这个字段了。

3.2.3 fill

表示是否自动填充。

在我们日常的开发工作中,数据库表里面通常都会有create_time、update_time字段,而这两个字段通常都是取当前时间来插入,我们就需要使用到自动填充。

我们现在数据库中新增create_time、update_time字段

图片

然后在实体类中新增两个属性​​​​​​​

/**
 * 创建时间
 */
@TableField(fill = FieldFill.INSERT)
private Date createTime;

/**
 * 更新时间
 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;

这里可以看到fill中还有FieldFill这个枚举类​​​​​​​

public enum FieldFill {
    DEFAULT,
    INSERT,
    UPDATE,
    INSERT_UPDATE;

    private FieldFill() {
    }
}

它这里代表四个动作:

  • DEFAULT:不填充

  • INSERT:在插入的时候填充

  • UPDATE:在更新的时候填充

  • INSERT_UPDATE:在插入或者更新时填充

做完这些,程序还不会帮我们自动去填充这两个字段,我们需要创建一个处理器​​​​​​​

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;

public class MyMetaObjectHandler implements MetaObjectHandler {
    
}

需要继承MetaObjectHandler这个接口,这是mybatisplus给我们提供的一个处理器,实现这个接口中的两个方法

图片


@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        // 此处的metaObject代表当前对象
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}

现在来保存数据试试​​​​​​​

@Test
void save() {
  User user = new User();
  user.setName("王五");
  user.setAge(30);
  mapper.insert(user);
}

图片

我们的两个时间已经顺利插入进来了。

3.3 @TableId

上面的@TableField注解是用来处理数据库中普通字段的,@TableId是用于处理主键字段的。

这注解中有几个属性需要重点关注一下:

3.3.1 value

映射主键id的字段名​​​​​​​

/**
 * 主键id
 */
@TableId(value = "id")
private Long userId;

3.3.2 type

设置主键类型,主键的生成策略。这个type的值是使用一组枚举类型来表示的,它一共有五种类型​​​​​​​

public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4),
    /** @deprecated */
    @Deprecated
    ID_WORKER(3),
    /** @deprecated */
    @Deprecated
    ID_WORKER_STR(3),
    /** @deprecated */
    @Deprecated
    UUID(4);

    private final int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}

其中用@Deprecated注解标注的类型表示已经被弃用,无需再关注。

类型描述
AUTO数据库自增
NONE(默认)MP来设置主键,使用雪花算法实现
INPUT需要自己给主键赋值
ASSIGN_IDMP使用Long、Integer、String来分配ID
ASSIGN_UUIDMP分配UUID

NONE

首先看一下默认的NONE类型。

在测试类中新增一个方法​​​​​​​

@Test
void save() {
  User user = new User();
  user.setName("赵六");
  user.setAge(12);
  mapper.insert(user);
}

执行后发现报错了

图片

提示我:Data truncation: Out of range value for column 'id' at row 1

由于NONE类型是雪花算法生成一串数字,所以推测应该是数据库中字段长度不够了。

我们改一下

图片

修改为BIGINT(100)

然后我们再来试一下

图片

可以看到数据已经插进去了,主键是1381086714713387010这一串雪花算法生成的数字。

INPUT​​​​​​​
/**
 * 主键id
 */
@TableId(type = IdType.INPUT)
private Long id;

这种类型比较简单,就是你手工在程序里给主键赋值,我这里就不演示了。

AUTO

这种方式就是交给数据库去处理,该自增自增。开发者无需处理了(就算你在程序里面手工给主键赋值,也只能按照数据库的自增来,相当于赋值无用)。

ASSIGN_ID 和 ASSIGN_UUID

​​​​​​​

/**
 * 主键id
 */
@TableId(type = IdType.ASSIGN_ID)
private Long id;

​​​​​​​

/**
 * 主键id
 */
@TableId(type = IdType.ASSIGN_UUID)
private String id;

当使用该属性,同样是MP采用雪花算法生成一个随机值,赋值给你类中id属性,并把该属性插入到数据库,和ASSIGN_UUID的区别在于,ASSIGN_UUID规定id必须是String类型,数据库字段必须是varchar类型,而且数据库原先的主键自增得去掉,否则也会报错,字符串类型是无法自增的。

3.4 @Version

标记乐观锁。

这里什么是乐观锁,我之后会给大伙们详细说一说。

通过 version 字段来保证数据的安全性,当修改修改数据的时候,会以 version 作为条件,当条件成立的时候,才会修改成功。

这里用到了一种乐观锁的思想,判断版本号是否和当前版本号相同,相同才可修改。

假设有两个线程同时修改一条数据,那么update语句就会是如下这样:

线程A:update ... set version = 2 where ... and version = 1;

线程B:update ... set version = 2 where ... and version = 1;

那么假如线程A先执行了,那么version就会被修改为2,线程B再执行时,就不会修改成功了。

那么我们怎么使用呢?

1. 我们在数据库表中新增一个version字段,默认值为1。

图片

2. 给实体类添加 version 成员变量​​​​​​​

/**
  * 乐观锁标记
  */
@Version
private Integer version;

3. 注册一个配置类​​​​​​​

@Configuration
public class MybatisPlusConfig {

    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

}

4. 把这个配置类加上后,我们的@Version应该就可以生效了,更新一条数据试试​​​​​​​

@Test
void update() {
  User user = mapper.selectById("1381088414421536771");
  user.setName("小明");
  mapper.updateById(user);
}

图片

SQL语句中已经出现更新version字段的信息了,看下数据库中的数据

图片

乐观锁已经生效。

3.5 @EnumValue

通用枚举类注解:将数据库字段映射成实体类的枚举类型成员变量。

我们在数据库中新增一个字段:status

图片

我们都知道通常状态都有几个固定的值。

我们在程序中新建一个枚举类​​​​​​​

public enum StatusEnum {
    /**
     * 在职
     */
    WORK(1, "在职"),
    /**
     * 离职
     */
    DEPARTURE(2, "离职");

    /**
     * 状态码
     */
    @EnumValue
    private Integer code;
    /**
     * 状态描述
     */
    private String desc;

    StatusEnum(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }
}

然后在实体类中增加一个字段​​​​​​​

但是到这里还没结束,我们还需要在配置文件application.yml中配置一下枚举包扫描​​​​​​​

mybatis-plus:
  #枚举包扫描
  type-enums-package: com.age.mybatisplus.enums

现在我们来查询一下

图片

可以看到这里的状态已经映射成功了。

实现枚举映射有两种方式,一种就是刚才讲的注解的方式,还有一种是实现接口的方式,这种我不细说了,感兴趣的小伙伴可以自己查询相关资(bai)料(du)。

3.6 @TableLogic

映射逻辑删除。

什么意思呢?

就是很多时候我们的数据,是不能真正删除的,只能进行逻辑删除,就是给它一个删除状态。

我们在表中新增一个字段:deleted

图片

实体类添加字段​​​​​​​

/**
 * 删除状态
 */
@TableLogic
private Integer deleted;

在application.yml中添加配置​​​​​​​

mybatis-plus:
  global-config:
    db-config:
      #逻辑删除配置 0-未删除;1-删除
      logic-not-delete-value: 0
      logic-delete-value: 1

测试类添加删除方法​​​​​​​

@Test
void delete() {
  mapper.deleteById("1381088414421536771");
}

图片

图片

我们的删除状态字段已经更新,那么这条数据我们还能查到吗?

图片

现在的查询语句中已经带上了deleted条件了,自然是查不到了。

关于MP一些常用的注解,就说这么多,顺带讲了基础的增删改查方法。

但是关于增删改查还有一些方法需要补充。

四、关于查询

4.1 selectList()

上面我们已经提到了这个方法,参数传null默认是查询全部数据。

如果我需要传递查询条件怎么弄?

List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

这里看到我们需要传递一个Wrapper对象,这个Wrapper对象就是用来封装查询条件的。

​​​​​​​

public abstract class Wrapper<T> implements ISqlSegment {
  
}

但是这个Wrapper是个接口,所以我们需要实例化它的实现类

QueryWrapper<User> wrapper = new QueryWrapper<>();

在QueryWrapper中有许多的方法,基本上都已经满足了日常的开发需求,关于一些常用的API,我们可以参考它的官网:

https://mp.baomidou.com/guide/wrapper.html#abstractwrapper

这里举一个简单的例子​​​​​​​

@Testvoid select() {  QueryWrapper<User> wrapper = new QueryWrapper<>();  wrapper.eq("name", "张三");  mapper.selectList(wrapper);}

图片

可以看到 name = '张三' 这个条件已经带上了。

多条件查询​​​​​​​

@Test
void select() {
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  Map<String, Object> map = new HashMap<>();
  map.put("name", "张三");
  map.put("age", 30);
  wrapper.allEq(map);
  mapper.selectList(wrapper);
}

图片

再来看一个联合查询​​​​​​​

@Test
void select() {
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  wrapper.inSql("id", "select id from user where id = '1381088414421536772'");
  mapper.selectList(wrapper);
}

图片

通过inSql这个方法,我们就可以自定义我们自己的SQL语句。

4.2 selectById()

通过主键查询。​​​​​​​

@Test
void select() {
  mapper.selectById("1381088414421536771");
}

4.3 selectBatchIds()

根据多个主键进行查询。​​​​​​​

@Test
void select() {
  mapper.selectBatchIds(Arrays.asList(
    "1381088414421536771", 
    "1381088414421536772", 
    "1381088414421536773"));
}

4.4 selectByMap()

用Map传递多个查询条件。和之前讲的Wrapper有点像,但是这里只能做等值查询,如果做范围查询则做不到。​​​​​​​

@Test
void select() {
  Map<String, Object> map = new HashMap<>();
  map.put("name", "张三");
  map.put("age", 30);
  mapper.selectByMap(map);
}

4.5 selectCount()

统计查询结果数量。​​​​​​​

@Test
void select() {
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name", "张三");
    mapper.selectCount(wrapper);
}

4.5 selectMaps()

将查询结果封装到Map中。​​​​​​​

@Test
void select() {
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  wrapper.eq("name", "张三");
  mapper.selectMaps(wrapper);
}

4.6 selectPage()

分页查询。

想要实现分页查询,我们需要做一下配置,在之前的配置类 MybatisPlusConfig 中添加方法​​​​​​​

@Bean
public PaginationInterceptor paginationInterceptor() {
  return new PaginationInterceptor();
}

否则分页不起作用。​​​​​​​

@Test
void select() {
  // Page构造方法有两个参数:current-当前页;size:-页大小
  Page<User> page = new Page<>(1, 10);
  // 返回值也是一个Page类型,里面包含了分页信息以及查询出来的数据信息。
  Page<User> result = mapper.selectPage(page, null);
  // 查询的结果在Records中
  result.getRecords().forEach(System.out::println);
}

4.7 selectMapsPage()

上面的selectPage()参数是Page封装一个Bean,这个方法的参数Page是封装一个Map。而且这里的返回值也是Map。​​​​​​​

@Test
void select() {
    Page<Map<String, Object>> page = new Page<>(1, 10);
    mapper.selectMapsPage(page, null).getRecords().forEach(System.out::println);
}

4.8 自定义SQL(多表关联查询)

现在我们需要再建一张业绩表:performance​​​​​​​

SET NAMES utf8mb4;

-- ----------------------------
-- Table structure for performance
-- ----------------------------
DROP TABLE IF EXISTS `performance`;
CREATE TABLE `performance`  (
  `id` bigint(100) NOT NULL COMMENT '主键id',
  `user_id` bigint(100) NOT NULL COMMENT '用户id',
  `score` int NOT NULL COMMENT '成绩',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '业绩表' ROW_FORMAT = Dynamic;

图片

我们添加一些数据

user表

图片

performance表

图片

假如现在我们的需求是查询出每个用户的id、name以及score,那么我们就需要用到关联查询。

我们需要先创建一个VO(视图层)

可能有一些小伙伴会疑惑什么时候使用VO,什么时候使用DTO?

这里简单解释一下:

如果你的数据是从数据库返回给视图层的(就是程序内部逻辑使用),就用VO。

如果你的数据是从数据库返回给业务层的(一般指我们的前端,或者处理数据的中台),就用DTO。​​​​​​​


@Data
public class PerformanceVO {
    /**
     * 用户id
     */
    private Long userId;
    /**
     * 用户名
     */
    private String userName;
    /**
     * 成绩
     */
    private Integer score;
}

然后在UserMapper中自定义我们的SQL语句

/**
 * 查询用户成绩
 * 
 * @param id 用户id
 * @return 用户成绩信息
 */
@Select("select u.id as userId, u.name as userName, p.score from user u, performance p where u.id = p.user_id and u.id = #{id}")
List<PerformanceVO> performanceList(long id);

然后我们来测试一下​​​​​​​

@Test
void performanceList() {
    mapper.performanceList(1381088414421536772L);
}

图片

可以看到查询已经成功执行啦。

五、关于添加

添加前面已经说过,这里不再赘述。

六、关于删除

除了前面讲到的 deleteById() 以外,还有以下一些删除的方法。

6.1 deleteBatchIds()

根据主键批量删除。​​​​​​​

@Test
void delete() {
  mapper.deleteBatchIds(Arrays.asList(1381088414421536772L, 1381396647736553474L));
}

6.2 delete()

根据指定条件删除。​​​​​​​

@Test
void delete() {
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  wrapper.eq("name", "张三");
  mapper.delete(wrapper);
}

6.3 deleteByMap()

也是根据指定条件删除,只不过这里是把条件装在Map里。​​​​​​​

@Test
void delete() {
  Map<String, Object> map = new HashMap<>();
  map.put("name", "张三");
  mapper.deleteByMap(map);
}

七、关于修改

前面已经讲过根据主键修改数据的方法 updateById() 。除此之外还有一个修改方法。

7.1 update()

根据特定条件修改数据。​​​​​​​

@Test
void update() {
  User user = mapper.selectById(1381088414421536772L);
  user.setName("王五");
  QueryWrapper<User> wrapper = new QueryWrapper<>();
  wrapper.eq("age", 30);
  mapper.update(user, wrapper);
}

这一段代码表示将年龄为30岁的用户名字修改为”王五“。

八、自动生成

MP还有一个很强大的功能就是可以根据你的数据表自动生成实体类、Mapper接口、Service、ServiceImpl、Controller。

挖槽?我连CRUD都不用做了?危!

8.1 导入依赖​​​​​​​

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-generator</artifactId>
  <version>3.3.1.tmp</version>
</dependency>
<dependency>
  <groupId>org.apache.velocity</groupId>
  <artifactId>velocity</artifactId>
  <version>1.7</version>
</dependency>

8.2 Main方法

我们需要写一个main方法​​​

/**
 * @author age
 * @since 2021/4/12
 */
public class Main {
    public static void main(String[] args) {
        // 创建generator对象
        AutoGenerator autoGenerator = new AutoGenerator();
        // 数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL)
                .setUrl("jdbc:mysql://localhost:3306/mp_test_db?useUnicode=true&characterEncoding=UTF-8")
                .setUsername("root")
                .setPassword("123456")
                .setDriverName("com.mysql.cj.jdbc.Driver");
        autoGenerator.setDataSource(dataSourceConfig);
        // 全局配置
        GlobalConfig globalConfig = new GlobalConfig();
        // 配置生成的类的路径
        globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");
        // 默认创建好文件路径后会把文件夹打开,这里我们把这个选项关闭
        globalConfig.setOpen(false);
        // 作者
        globalConfig.setAuthor("age");
        autoGenerator.setGlobalConfig(globalConfig);
        // 包信息
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setParent("com.age.mybatisplus");
        // 会在com.age.mybatisplus路径下创建一个generator的包
        packageConfig.setModuleName("generator");
        // controller包名
        packageConfig.setController("controller");
        // service包名
        packageConfig.setService("service");
        // serviceImpl包名
        packageConfig.setServiceImpl("service.impl");
        // mapper包名
        packageConfig.setMapper("mapper");
        // entity包名
        packageConfig.setEntity("entity");
        autoGenerator.setPackageInfo(packageConfig);
        // 配置策略
        StrategyConfig strategyConfig = new StrategyConfig();
        // 实体类中启用lombok
        strategyConfig.setEntityLombokModel(true);
        // 实体类中字段名映射下划线转驼峰
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
        autoGenerator.setStrategy(strategyConfig);

        autoGenerator.execute();
    }
}

执行这个main方法

图片

图片

舒服吗?

看到这里,你还能心安理得的CRUD吗?赶紧学点东西吧,CRUD都不需要人来做了!

九、总结

Mybatis Plus是一款非常便捷的开发工具,目前在很多企业中也都广泛使用,大大提高我们的开发效率,使我们更加专注于业务逻辑的编写,其他模板化的东西,就交给MP来解决吧。

以上就是本文要介绍的所有内容,感谢您的阅读

标签:一学,private,id,Plus,user,Mybatis,new,查询,主键
From: https://blog.csdn.net/qq_41320700/article/details/143837356

相关文章

  • 01MybatisPlus(SpringCloud入门必学!!!!微服务!!项目实战!!深度理解MP用法!!!)
    微服务springCloud,今天第一课就是MybatisPlus!!!大家在日常开发中应该能发现,单表的CRUD功能代码重复度很高,也没有什么难度。而这部分代码量往往比较大,开发起来比较费时。        因此,目前企业中都会使用一些组件来简化或省略单表的CRUD开发工作。目前在国内使用较多的......
  • 免费Office Tool Plus使用教程
    1.下载OfficeToolPlushttps://otp.landian.vip/zh-cn/2.安装3.激活输入命令:ospp/insLicIDMondoVolume/sethst:kms.loli.beer/setprt:1688/act可以免费的使用office了......
  • MybatisPlus动态表名
    官网文档https://baomidou.com/plugins/dynamic-table-name/Java代码配置拦截器importcom.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;importorg.spring......
  • Mybatis 常见异常
    Mybatis列表查询只返回了部分数据,Sql语句多出limit异常//list查询接口List<Info>infoList=xxxMapper.selectList();列表查询接口,只返回了部分数据原因通过日志观察,发现日志打印的sql多了limit参数,怀疑时与分页有关;基于此,搜索资料发现,PageHelper插件是通过ThreadLoc......
  • Swagger 3.0 & MybatisPlus 主键BigDecimal 使用过程问题
    PS:本来用的是2.x的,但是因为换了后端框架,导致版本不适配,于是调整到3.0<dependency><groupId>io.springfox</groupId><artifactId>springfox-boot-starter</artifactId><version>3.0.0</version>&......
  • 使用Mybatis-plus进行分页查询,没有分页效果,查询的数据量超出每页数量设置
    原因:没有开启分页插件。 解决办法:需要新增或者在原myabtis-plus配置类中新增分页插件,具体代码如下importcom.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;importcom.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterc......
  • 在Unity中使用Epplus写Excel
    Overview    本文旨在帮助你快速入门,该库发展多年内容庞大(官方文档写的极好:https://github.com/EPPlusSoftware/EPPlus/wiki),有些功能在Unity环境可能你永远都不会使用.官方的一个Demo:https://github.com/EPPlusSoftware/EPPlus.Samples.CSharp如果你只有读的......
  • 201117 noi plus 模拟赛
    省流:\(40+85+48+0\)。逆天绿紫黑黑。不能再挂分了,t1\(100\to40\),t2\(100\to85\),t3\(84\to48\)。T1给一个\(n\timesm\)的网格图,每个点只能是#或.或S或T,若这个点为#则这个点是障碍,不能到达,若是.则是空地,可以到达,S是起点,T是终点。每次你可以走四联......
  • MyBatis封装成工具类:入门大学生的极限
    第一篇SDN文章,也不咋会写。这是自己总结了很久才实现的。废话少说直接上代码。我得先研究一下代码咋弄上来。欧克。找到了。那么展示。这是是主工具java类:publicclassMybatisTool{//构造方法私有化privateMybatisTool(){}//静态内部类privates......
  • Element Plus
    快速入门:然后我在src下创建了一个Button.vue文件,再去Element-plus官网查找组件的源码常用组件表格:<scriptlang="ts"setup>import{Delete,Edit,}from'@element-plus/icons-vue'consttableData=[{title:'标题1',category:&#......