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: 8080spring:datasource:url: jdbc:mysql://localhost:3306/mybatisplus?characterEncoding=utf-8&serverTimezone=UTCusername: rootpassword: 5247driver-class-name: com.mysql.cj.jdbc.Driver
3.创建mybatisplus数据库
/*Navicat Premium Data TransferSource Server : jfSource Server Type : MySQLSource Server Version : 80013Source Host : localhost:3306Source Schema : mybatisplusTarget Server Type : MySQLTarget Server Version : 80013File Encoding : 65001Date: 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@AllArgsConstructorpublic 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;@SpringBootTestpublic class Test01 {@Autowiredprivate StudentMapper studentMapper;@Testpublic 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:# 默认值为truemap-underscore-to-camel-case: trueglobal-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:# 默认值为truemap-underscore-to-camel-case: true# 启动mybatis本身的log日志log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-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@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic 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)}@Overridepublic 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方法来进行数据插入
@Testpublic void insertTest(){Student student = new Student();student.setName("张三");student.setAge(22);int res = studentMapper.insert(student);System.out.println(res);}
删除数据
- deleteById
@Testpublic void deleteByIdTest(){int res = studentMapper.deleteById(17);System.out.println(res);}
- deleteBatchIds
@Testpublic 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
@Testpublic 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
@Testpublic 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 字段
等等…具体查阅官网
示例
@Testpublic void queryWrapperTest01(){QueryWrapper<Student> wrapper = new QueryWrapper<>();wrapper.eq("name","张三");wrapper.gt("age",20);List<Student> students = studentMapper.selectList(wrapper);System.out.println(students);}@Testpublic 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);}@Testpublic 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方法
示例
@Testpublic void selectQueryWrapperTest01(){QueryWrapper<Student> wrapper = new QueryWrapper<>();wrapper.select("id","name","age");List<Student> students = studentMapper.selectList(wrapper);System.out.println(students);}@Testpublic void selectQueryWrapperTest02(){QueryWrapper<Student> wrapper = new QueryWrapper<>();wrapper.select(Student.class, new Predicate<TableFieldInfo>() {@Overridepublic boolean test(TableFieldInfo tableFieldInfo) {return "name".equals(tableFieldInfo.getColumn());}});List<Student> students = studentMapper.selectList(wrapper);System.out.println(students);}
常用updateWrapper方法
示例
@Testpublic 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);}@Testpublic 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用法
示例
@Testpublic 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;@Servicepublic class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {}
- 测试
@Autowiredprivate StudentService studentService;@Testpublic 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());}}
