# mybatis-plus-demo
**Repository Path**: jayem/mybatis-plus-demo
## Basic Information
- **Project Name**: mybatis-plus-demo
- **Description**: 适合人群 - 小白就算了吧!
1. 熟练并使用过mybatis框架
2. 熟练并使用过springboot框架
3. 熟练并使用sql语句
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 2
- **Created**: 2021-12-28
- **Last Updated**: 2021-12-28
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 目录
[TOC]
# 1. 人生苦短

# 2. Mybatis-Plus简介
> 1. [MyBatis-Plus (opens new window)](https://github.com/baomidou/mybatis-plus)(简称 MP)是一个 [MyBatis (opens new window)](http://www.mybatis.org/mybatis-3/)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生
> 2. 官网指南 - https://baomidou.com/guide/
# 3. 适合人群
> 1. 拥有 Java 开发环境以及相应 IDE
>
> 2. 熟悉 Spring Boot
>
> 3. 熟悉 Maven
> 4. 熟悉mybatis框架
#4. 快速开始
> 1. 创建SpringBoot工程
>
> 2. 导入依赖
>
> ~~~xml
>
> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
> 4.0.0
>
> org.springframework.boot
> spring-boot-starter-parent
> 2.5.0
>
>
> tech.aistar
> mybatis-plus-demo
> 0.0.1-SNAPSHOT
> mybatis-plus-demo
> Demo project for Spring Boot
>
> 1.8
>
>
>
> org.springframework.boot
> spring-boot-starter-web
>
>
>
> mysql
> mysql-connector-java
> runtime
>
>
> org.projectlombok
> lombok
> true
>
>
> org.springframework.boot
> spring-boot-starter-test
> test
>
>
> com.baomidou
> mybatis-plus-boot-starter
> 3.4.3
>
>
>
>
>
>
> org.springframework.boot
> spring-boot-maven-plugin
>
>
>
> org.projectlombok
> lombok
>
>
>
>
>
>
>
> ~~~
>
> 3. 表设计
>
> ~~~sql
> DROP TABLE IF EXISTS user;
> CREATE TABLE user (
> id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',
> name VARCHAR(30) DEFAULT NULL COMMENT '姓名',
> age INT(11) DEFAULT NULL COMMENT '年龄',
> email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
> manager_id BIGINT(20) DEFAULT NULL COMMENT '直属上级id',
> create_time DATETIME DEFAULT NULL COMMENT '创建时间',
> CONSTRAINT manager_fk FOREIGN KEY(manager_id) REFERENCES user (id)
> ) ENGINE=INNODB CHARSET=UTF8;
>
> INSERT INTO user (id, name, age ,email, manager_id, create_time) VALUES
> (1, '大BOSS', 40, 'boss1@baomidou.com', NULL, '2021-03-22 09:48:00'),
> (2, '李三儿', 30, 'boss2@baomidou.com', 1, '2021-01-22 09:48:00'),
> (3, '黄小三', 35, 'boss3@baomidou.com', 2, '2021-01-22 09:48:00'),
> (4, '三德子', 25, 'boss4@baomidou.com', 2, '2021-02-22 09:48:00'),
> (5, '小菜', 23, 'boss5@baomidou.com', 2, '2021-02-22 09:48:00'),
> (6, '黄主任',23,NULL,5, '2021-02-22 09:48:00');
> ~~~
>
> 4. 实体类
>
> ~~~java
> package tech.aistar.pojo;
>
> import lombok.Data;
>
> import java.io.Serializable;
> import java.util.Date;
>
> /**
> * 本类用来演示: 用户实体类
> *
> * @author: success
> * @date: 2021/5/31 9:51 上午
> */
> @Data
> public class User implements Serializable {
> private Long id;
> private String name;
> private Integer age;
> private String email;
> private Long managerId;
> private Date createTime;
> }
> ~~~
>
> 5. application.yml文件配置
>
> ~~~yml
> spring:
> datasource:
> url: jdbc:mysql://localhost:3306/dev?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
> driver-class-name: com.mysql.cj.jdbc.Driver
> username: root
> password: root
> mybatis-plus:
> configuration:
> log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
> ~~~
>
> 6. 主程序类
>
> ~~~java
> package tech.aistar;
>
> import org.mybatis.spring.annotation.MapperScan;
> import org.springframework.boot.SpringApplication;
> import org.springframework.boot.autoconfigure.SpringBootApplication;
>
> @MapperScan("tech.aistar.mapper")
> @SpringBootApplication
> public class MybatisPlusDemoApplication {
>
> public static void main(String[] args) {
> SpringApplication.run(MybatisPlusDemoApplication.class, args);
> }
> }
> ~~~
>
> 7. 单元测试
>
> ~~~java
> package tech.aistar.mapper;
>
> import org.junit.jupiter.api.Test;
> import org.springframework.beans.factory.annotation.Autowired;
> import org.springframework.boot.test.context.SpringBootTest;
>
> /**
> * 本类用来演示:
> *
> * @author: success
> * @date: 2021/5/31 11:14 上午
> */
> @SpringBootTest
> public class UserMapperTest {
> @Autowired
> private UserMapper userMapper;
> /**
> * 测试 - 查询所有
> */
> @Test
> public void testFindAll(){
> userMapper.selectList(null).forEach(System.out::println);
> }
> }
> ~~~
`总结:可以看到,针对单表的基本CRUD操作,只需要创建好实体类,并创建一个继承自BaseMapper的接口即可,可谓非常简洁。并且,我们注意到,User类中的managerId,createTime属性,自动和数据库表中的manager_id,create_time对应了起来,这是因为mp自动做了数据库下划线命名,到Java类的驼峰命名之间的转化。`
# 5. 核心功能
`注解`
mp一共提供了8个注解,这些注解是用在Java的实体类上面的。
1. @TableName
> 注解在类上,指定类和数据库表的映射关系。**实体类的类名(转成小写后)和数据库表名相同时**,可以不指定该注解。
2. @TableId
> 注解在实体类的某一字段上,**表示这个字段对应数据库表的主键**。当主键名为id时(表中列名为id,实体类中字段名为id),无需使用该注解显式指定主键,mp会自动关联。若类的字段名和表的列名不一致,可用`value`属性指定表的列名。另,这个注解有个重要的属性`type`,用于指定主键策略。
3. @TableField
> 注解在某一字段上,指定Java实体类的字段和数据库表的列的映射关系。这个注解有如下几个应用场景。
>
> - **排除非表字段**
>
> 若Java实体类中某个字段,不对应表中的任何列,它只是用于保存一些额外的,或组装后的数据,则可以设置`exist`属性为`false`,这样在对实体对象进行插入时,会忽略这个字段。排除非表字段也可以通过其他方式完成,如使用`static`或`transient`关键字,但个人觉得不是很合理,不做赘述
>
> - **字段验证策略**
>
> 通过`insertStrategy`,`updateStrategy`,`whereStrategy`属性进行配置,可以控制在实体对象进行插入,更新,或作为WHERE条件时,对象中的字段要如何组装到SQL语句中。
>
> - **字段填充策略**
>
> 通过`fill`属性指定,字段为空时会进行自动填充
4. @Version
> 乐观锁注解
5. @EnumValue
> 注解在枚举字段上
6. @TableLogic
> 逻辑删除
7. @KeySequence
> 序列主键策略(`oracle`)
8. @InterceptorIgnore
> 插件过滤规则
# 6. CRUD接口
> 1. mp封装了一些最基础的CRUD方法,只需要直接继承mp提供的接口,无需编写任何SQL,即可食用。
>
> 2. mp提供了两套接口,分别是Mapper CRUD接口和Service CRUD接口。
>
> 3. 并且mp还提供了条件构造器`Wrapper`,可以方便地组装SQL语句中的WHERE条件
## 6.1 Mapper CRUD接口
> - 通用 CRUD 封装[BaseMapper (opens new window)](https://gitee.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/mapper/BaseMapper.java)接口,
>
> 为 `Mybatis-Plus` 启动时自动解析实体表关系映射转换为 `Mybatis` 内部对象注入容器
>
> - 泛型 `T` 为任意实体对象
>
> - 参数 `Serializable` 为任意类型主键 `Mybatis-Plus` ***不推荐使用复合主键约定每一张表都有自己的唯一 `id` 主键***
>
> - 对象 `Wrapper` 为 [条件构造器](https://baomidou.com/guide/wrapper.html)
>
> **学习目标 - `BaseMapper`里提供的方法**
### 6.1.1 Insert方法
~~~java
// 插入一条记录
int insert(T entity);
~~~
`参数说明`
| 类型 | 参数名 | 描述 |
| :--: | :----: | :------: |
| T | entity | 实体对象 |
`测试代码`
~~~java
/**
* 测试Insert方法
*/
@Test
public void testInsert(){
User user = new User();
user.setName("success");
user.setAge(18);
user.setEmail("849962874@qq.com");
user.setCreateTime(new Date());
user.setManagerId(2L);
userMapper.insert(user);
}
~~~
### 6.1.2 Delete方法
~~~java
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
~~~
`参数说明`
| 类型 | 参数名 | 描述 |
| :--------------------------------: | :-------: | :--------------------------------: |
| Wrapper | wrapper | 实体对象封装操作类(可以为 null) |
| Collection extends Serializable> | idList | 主键ID列表(不能为 null 以及 empty) |
| Serializable | id | 主键ID |
| Map | columnMap | 表字段 map 对象 |
`测试代码`
~~~java
@Test
public void testDelete(){
//根据 ID 删除
//userMapper.deleteById(1399249825152729090L);
//删除(根据ID 批量删除)
// List ids = new ArrayList<>();
// ids.add(5L);
// ids.add(3L);
// userMapper.deleteBatchIds(ids);
// 根据 entity 条件,删除记录
//DELETE FROM user WHERE (manager_id = ?)
// QueryWrapper queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("manager_id",2L);
// userMapper.delete(queryWrapper);
//根据 columnMap 条件,删除记录
//DELETE FROM user WHERE name = ?
Map maps = new HashMap<>();
maps.put("name","吴组长");
userMapper.deleteByMap(maps);
}
~~~
### 6.1.3 Update方法
~~~java
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);
~~~
`参数说明`
| 类型 | 参数名 | 描述 |
| :--------: | :-----------: | :----------------------------------------------------------: |
| T | entity | 实体对象 (set 条件值,可为 null) |
| Wrapper | updateWrapper | 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) |
`测试代码`
~~~java
@Test
public void testUpdate(){
// User user = userMapper.selectById(1L);
// user.setName("success");
// userMapper.updateById(user);
//第一种写法 - 使用set()方法单独更新某个列
// UpdateWrapper updateWrapper = new UpdateWrapper<>();
// updateWrapper.ge("age",40).set("age",100);
//
// userMapper.update(null,updateWrapper);
//第二种写法 - 使用对象
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.ge("age",23).le("age",30);
User user = new User();
user.setAge(18);
userMapper.update(user,updateWrapper);
}
~~~
### 6.1.4 Select方法
~~~java
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper);
// 查询(根据ID 批量查询)
List selectBatchIds(@Param(Constants.COLLECTION) Collection extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);
// 查询(根据 columnMap 条件)
List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
// 根据 Wrapper 条件,查询全部记录
List