MyBatisPlus学习笔记
Posted 康小庄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatisPlus学习笔记相关的知识,希望对你有一定的参考价值。
文章目录
- MyBatisPlus学习笔记
- 简介
- 快速使用
- 注解
- #[@TableName(opens new window)](https://github.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/TableName.java)
- [@TableId(opens new window)](https://github.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/TableId.java)
- #[@TableField(opens new window)](https://github.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/TableField.java)
- [@TableLogic(opens new window)](https://github.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/TableLogic.java)
- [@OrderBy(opens new window)](https://gitee.com/baomidou/mybatis-plus/blob/3.0/mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/OrderBy.java)
- MyBatisPlus的条件构造器
- 代码生成器
MyBatisPlus学习笔记
简介
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
愿景
我们的愿景是成为 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-Plus (baomidou.com)
文档:简介 | MyBatis-Plus (baomidou.com)
框架结构
快速使用
创建项目步骤不再赘述,此文章是快速上手MP,其余步骤自行搜索!!
开发环境
JDK:jdk1.8
IDE:IntelliJ IDEA 2020.2.3 x64
Maven:apache-maven-3.6.3
MYSQL:mysql5.5
引入mybatis-plus相关maven依赖
<!--mybatis-plus依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.2</version>
</dependency>
引入mybatis-plus在spring boot中的场景启动器
<!--SpringBoot启动器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
ps:切记不可再在pom.xml文件中引入mybatis与mybatis-spring的maven依赖,这一点,mybatis-plus的官方文档中已经
说明的很清楚了
项目中其他需要导入依赖
<!--mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--Druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
创建表SQL语句
CREATE DATABASE mp;
USE mp;
CREATE TABLE tbl_employee(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(50),
email VARCHAR(50),
gender CHAR(1),
age INT
);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom','tom@atguigu.com',1,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Jerry','jerry@atguigu.com',0,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Black','black@atguigu.com',1,30);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('White','white@atguigu.com',0,35);
SELECT * FROM tbl_employee;
项目结构一览
项目配置
配置MapperScan注解
application.properties配置
#mysql
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#mybatis-plus查看SQL语句
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
创建Entity(Pojo)实体
src/main/java/com/zhuang/pojo
使用lombok
插件简化代码
package com.zhuang.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
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 lombok.ToString;
import org.springframework.stereotype.Component;
/**
* @Classname Employee
* @Description 实体类
* @Date 2021/10/23 8:49
* @Author by zhuang
*/
@Component
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName("tbl_employee")
public class Employee {
/**
* TableId 注解对应数据库字段,防止识别失败
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(value = "last_name")
private String lastName;
@TableField(value = "email")
private String email;
@TableField(value = "gender")
private Integer gender;
@TableField(value = "age")
private Integer age;
}
创建接口
注意注解要加!
package com.zhuang.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhuang.pojo.Employee;
import org.springframework.stereotype.Repository;
/**
* @Classname EmployeeMapper
* @Description Mapper接口
* @Date 2021/10/23 8:51
* @Author by dell
*/
@Repository
public interface EmployeeMapper extends BaseMapper<Employee> {
}
普通的CRUD操作
直接看代码!
package com.zhuang.mybatisplus;
import com.zhuang.mapper.EmployeeMapper;
import com.zhuang.pojo.Employee;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private EmployeeMapper employeeMapper;
/**
* 插入一条数据的测试
*/
@Test
public void insert() {
int result = employeeMapper.insert(new Employee(null, "zhuangkang", "123@qq.com", 0, 18));
System.out.println(result);
}
/**
* 通过Id修改数据
*/
@Test
public void updateById() {
// 先查询
Employee employee = employeeMapper.selectById(1);
employee.setLastName("123zk");
// 再执行修改
int result = employeeMapper.updateById(employee);
System.out.println(result);
}
/**
* 查询id为1的员工信息
*/
@Test
public void queryById() {
Employee employee = employeeMapper.selectById(1);
System.out.println(employee);
}
/**
* 查询性别为男性(0)且年龄在25岁的员工信息
*/
@Test
public void selectByIdMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("gender", 0);
map.put("age", 25);
List<Employee> employees = employeeMapper.selectByMap(map);
employees.forEach(System.out::println);
}
/**
* 查询id分别为1、2、3的员工的信息
*/
@Test
public void queryBatch() {
List<Employee> employees = employeeMapper.selectBatchIds(Arrays.asList(1, 2, 3));
employees.forEach(System.out::println);
}
/**
* 删除id为1的员工信息
*/
@Test
public void deleteById() {
int result = employeeMapper.deleteById(1);
System.out.println(result);
}
/**
* 删除性别为男性(0)且年龄在25岁的员工信息
*/
@Test
public void deleteByMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("gender", 0);
map.put("age", 25);
int result = employeeMapper.deleteByMap(map);
System.out.println(result);
}
/**
* 删除id分别为3、8、9的员工的信息
*/
@Test
public void deleteBatch() {
int result = employeeMapper.deleteBatchIds(Arrays.asList(3, 8, 9));
System.out.println(result);
}
}
注意
有时候IDEA会抽风,识别不到Mapper,出现下列情况可以忽略
注解
这里只介绍常用的,具体可去官方文档查询 注解 | MyBatis-Plus (baomidou.com)
#@TableName(opens new window)
- 描述:表名注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 表名 |
schema | String | 否 | “” | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值) |
resultMap | String | 否 | “” | xml 中 resultMap 的 id |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入) |
excludeProperty | String[] | 否 | {} | 需要排除的属性名(@since 3.3.1) |
@TableId(opens new window)
- 描述:主键注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 主键字段名 |
type | Enum | 否 | IdType.NONE | 主键类型 |
#IdType(opens new window)
值 | 描述 |
---|---|
AUTO | 数据库ID自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert前自行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 ) |
UUID | 32位UUID字符串(please use ASSIGN_UUID ) |
ID_WORKER_STR | 分布式全局唯一ID 字符串类型(please use ASSIGN_ID ) |
#@TableField(opens new window)
- 描述:字段注解(非主键)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 数据库字段名 |
el | String | 否 | “” | 映射为原生 #{ ... } 逻辑,相当于写在 xml 里的 #{ ... } 部分 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | “” | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s} ,参考(opens new window) |
update | String | 否 | “” | 字段 update set 部分注入, 例如:update="%s+1":表示更新时会set version=version+1(该属性优先级高于 el 属性) |
insertStrategy | Enum | N | DEFAULT | 举例:NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | N | DEFAULT | 举例:IGNORED: update table_a set column=#{columnProperty} |
whereStrategy | Enum | N | DEFAULT | 举例:NOT_EMPTY: where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC类型 (该默认值不代表会按照该值生效) |
typeHandler | Class<? extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | “” | 指定小数点后保留的位数 |
@TableLogic(opens new window)
- 描述:表字段逻辑处理注解(逻辑删除)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 逻辑未删除值 |
delval | String | 否 | “” | 逻辑删除值 |
@OrderBy(opens new window)
- 描述:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
isDesc | boolean | 否 | 是 | 是否倒序查询 |
sort | short | 否 | Short.MAX_VALUE | 数字越小越靠前 |
MyBatisPlus的条件构造器
构造器是个很强大的东西,简化开发很多,通过 EntityWrapper(简称 EW,MP 封装的一个查询条件构造器)或者 Condition(与 EW 类似) 来让用户自由的构建查询条件,简单便捷,没有额外的负担, 能够有效提高开发效率,它主要用于处理 sql 拼接,排序,实体参数查询。
注意:使用的是数据库字段,不是 Java 属性!
警告:MyBatis-Plus不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输,Wrapper 很重,传输 Wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场),正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
说明:
- 以下出现的第一个入参
boolean condition
表示该条件是否加入最后生成的sql中,例如:query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age) - 以下代码块内的多个方法均为从上往下补全个别
boolean
类型的入参,默认为true
- 以下出现的泛型
Param
均为Wrapper
的子类实例(均具有AbstractWrapper
的所有方法) - 以下方法在入参中出现的
R
为泛型,在普通wrapper中是String
,在LambdaWrapper中是函数(例:Entity::getId
,Entity
为实体类,getId
为字段id
的getMethod) - 以下方法入参中的
R column
均表示数据库字段,当R
具体类型为String
时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)!而不是实体类数据字段名!!!,另当R
具体类型为SFunction
时项目runtime不支持eclipse自家的编译器!!! - 以下举例均为使用普通wrapper,入参为
Map
和List
的均以json
形式表现! - 使用中如果入参的
Map
或者List
为空,则不会加入最后生成的sql中!!!
Warrper结构
常用方法
只介绍常用的,具体请跳转👉条件构造器 | MyBatis-Plus (baomidou.com)
/**
* 查询员工年龄小于30
*/
@Test
public void queryForList() {
QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
queryWrapper.lt("age", 30);
List<Employee> employees = employeeMapper.selectList(queryWrapper);
employees.forEach(System.out::println);
}
/**
* 查询所有员工信息
*/
@Test
public void queryAll() {
QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
List<Employee> employees = empl以上是关于MyBatisPlus学习笔记的主要内容,如果未能解决你的问题,请参考以下文章
[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段