mybatis-plus学习
概述
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
快速入门
构建springboot项目
1.引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--添加配置跳过测试-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!--添加配置跳过测试-->
</plugins>
</build>
2.配置application.yaml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatisplus?characterEncoding=utf-8&serverTimezone=UTC
username: root
password: 5247
driver-class-name: com.mysql.cj.jdbc.Driver
3.创建mybatisplus数据库
/*
Navicat Premium Data Transfer
Source Server : jf
Source Server Type : MySQL
Source Server Version : 80013
Source Host : localhost:3306
Source Schema : mybatisplus
Target Server Type : MySQL
Target Server Version : 80013
File Encoding : 65001
Date: 21/06/2022 19:59:27
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '学生id主键',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '学生姓名',
`age` int(10) NULL DEFAULT NULL COMMENT '姓名',
`sex` int(2) NULL DEFAULT NULL COMMENT '性别,1为男,2为女',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '住址',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
4.创建Student对象
package gdut.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Long id;
private String name;
private Integer age;
private boolean sex;
private String address;
private Date createTime;
}
5.创建SutdentMapper
package gdut.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import gdut.domain.Student;
public interface StudentMapper extends BaseMapper<Student> {
}
6.创建MyApplication启动类
package gdut.edu;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("gdut.mapper")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class,args);
}
}
7.测试(先向数据库插入几条数据)
package gdut.edu;
import gdut.domain.Student;
import gdut.mapper.StudentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class Test01 {
@Autowired
private StudentMapper studentMapper;
@Test
public void test01() {
List<Student> students = studentMapper.selectList(null);
System.out.println(students);
}
}
常用设置
设置表映射规则
默认情况下,MP操作的表名就是实体类的类名,如果实体类类名和数据库对应的表名不一致,需要我们自行设置映射规则
单独设置
在实体类类名上加@TableName注解标识,如果表名时tb_student,而实体类类名是Student,使用如下写法
package gdut.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_student")
public class Student {
private Long id;
private String name;
private Integer age;
private boolean sex;
private String address;
private Date createTime;
}
全局设置表名前缀
如果我们很多表名和实体类类名不对应,但是表名都只是在类名的基础上在其前面加了个前缀,比如tb_
,实体类为User,表名为tb_user,这样的情况下我们可以全局设置表名前缀
mybatis-plus:
global-config:
db-config:
# 表名前缀
table-prefix: tb_
主键生成策略
单独设置
使用MP插入数据时,如果在我们没有设置主键生成策略的情况下默认的策略是基于雪花算法的自增id。如果我们需要使用别的策略可以在定义实体类时,在代表主键的字段上加上@TableId注解,使用其type属性指定主键生成策略。
package gdut.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName("tb_student")
public class Student {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private boolean sex;
private String address;
private Date createTime;
}
全局设置
mybatis-plus:
global-config:
db-config:
# id生成策略,auto为数据库自增
id-type: auto
IdType
值 | 描述 |
---|---|
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 ) |
驼峰命名
是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射。
mybatis-plus:
configuration:
# 默认值为true
map-underscore-to-camel-case: true
global-config:
db-config:
# 表名前缀
table-prefix: tb_
# id-type: auto
@TableField
- 描述:字段注解(非主键)
package gdut.domain;
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 java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
//@TableName("tb_student")
public class Student {
@TableId(type = IdType.AUTO)
private Long id;
@TableField("nickname")
private String name;
private Integer age;
private boolean sex;
private String address;
private Date createTime;
}
启动mybatis本身的log日志
mybatis-plus:
configuration:
# 默认值为true
map-underscore-to-camel-case: true
# 启动mybatis本身的log日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
# 表名前缀
table-prefix: tb_
# id-type: auto
自动填充功能
原理:
- 实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
- 注解填充字段
@TableField(.. fill = FieldFill.INSERT)
生成器策略部分也可以配置!
public class User {
// 注意!这里需要标记为填充字段
@TableField(.. fill = FieldFill.INSERT)
private String fillField;
....
}
- 自定义实现类 MyMetaObjectHandler
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
// 或者
this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
// 或者
this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
// 或者
this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
}
}
分页
有bug
基本操作
插入数据
- 使用insert方法来进行数据插入
@Test
public void insertTest(){
Student student = new Student();
student.setName("张三");
student.setAge(22);
int res = studentMapper.insert(student);
System.out.println(res);
}
删除数据
- deleteById
@Test
public void deleteByIdTest(){
int res = studentMapper.deleteById(17);
System.out.println(res);
}
- deleteBatchIds
@Test
public void deleteBacthIdsTest(){
ArrayList<Integer> idList = new ArrayList<>();
idList.add(15);
idList.add(16);
idList.add(14);
int res = studentMapper.deleteBatchIds(idList);
System.out.println(res);
}
- deleteByMap
@Test
public void deleteByMapTest(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","张三");
map.put("age",22);
int res = studentMapper.deleteByMap(map);
System.out.println(res);
}
更新操作
- update
@Test
public void updateTest(){
Student student = new Student();
student.setId(19L);
student.setAge(33);
int res = studentMapper.updateById(student);
System.out.println(res);
}
条件构造器wrapper
AbstractWrapper
说明:
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
常用AbstractWrapper方法
- eq 等于=
- ne 不等于<>
- gt 大于>
- ge 大于等于>=
- lt 小于<
- le 小于等于<=
- between between 值1 and 值2
- notBetween not between 值2 and 值2
- like like”%值%”
- notLike not like “%值%”
- likeLeft like”%值”likeRight like”值%”
- likeRight like”值%”
- isNull 字段 is null
- isNotNull 字段 is not null
- in 字段 in (value1,value2…)
- notIN 字段 not in (value1,value2…)
- groupBy 分组group by 字段
等等…具体查阅官网
示例
@Test
public void queryWrapperTest01(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.eq("name","张三");
wrapper.gt("age",20);
List<Student> students = studentMapper.selectList(wrapper);
System.out.println(students);
}
@Test
public void queryWrapperTest02(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.like("name","三");
wrapper.between("age",10,33);
List<Student> students = studentMapper.selectList(wrapper);
System.out.println(students);
}
@Test
public void queryWrapperTest03(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.eq("sex",true);
wrapper.gt("id",10);
wrapper.orderByDesc("age");
List<Student> students = studentMapper.selectList(wrapper);
System.out.println(students);
}
常用queryWrapper方法
示例
@Test
public void selectQueryWrapperTest01(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.select("id","name","age");
List<Student> students = studentMapper.selectList(wrapper);
System.out.println(students);
}
@Test
public void selectQueryWrapperTest02(){
QueryWrapper<Student> wrapper = new QueryWrapper<>();
wrapper.select(Student.class, new Predicate<TableFieldInfo>() {
@Override
public boolean test(TableFieldInfo tableFieldInfo) {
return "name".equals(tableFieldInfo.getColumn());
}
});
List<Student> students = studentMapper.selectList(wrapper);
System.out.println(students);
}
常用updateWrapper方法
示例
@Test
public void updateWrapperTest01(){
UpdateWrapper<Student> updateWrapper = new UpdateWrapper<>();
updateWrapper.gt("id",11);
updateWrapper.set("age",99);
int res = studentMapper.update(null, updateWrapper);
System.out.println(res);
}
@Test
public void updateWrapperTest02(){
UpdateWrapper<Student> updateWrapper = new UpdateWrapper<>();
updateWrapper.gt("id",11);
updateWrapper.set("age",88);
int res = studentMapper.update(new Student(), updateWrapper);
System.out.println(res);
}
LamdaQueryWrapper用法
示例
@Test
public void lamdaQueryWrapperTest01() {
LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Student::getName, "张三");
queryWrapper.gt(Student::getAge, 22);
List<Student> students = studentMapper.selectList(queryWrapper);
System.out.println(students);
}
Service层接口
- 接口
package gdut.service;
import com.baomidou.mybatisplus.extension.service.IService;
import gdut.domain.Student;
public interface StudentService extends IService<Student> {
}
- 实现类
package gdut.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import gdut.domain.Student;
import gdut.mapper.StudentMapper;
import gdut.service.StudentService;
import org.springframework.stereotype.Service;
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
}
- 测试
@Autowired
private StudentService studentService;
@Test
public void testService(){
System.out.println(studentService);
LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Student::getAge,88);
queryWrapper.gt(Student::getId,12);
List<Student> studentList = studentService.list(queryWrapper);
Iterator<Student> iterator = studentList.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}