入门案例
MyBatisPlus是基于Mybatis框架基础上开发的增强型工具,旨在简化开发,提高效率。具有无侵入、强大的CRUD,支持Lambda、支持主键自动生成、内置分页插件等等实用的功能。
1.导入相关的数据库,创建一个名为mp_db的数据库,字符集选择utf8mb4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, `password` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL, `age` int(3) NOT NULL, `tel` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
INSERT INTO `user` VALUES (1, 'Tom', 'tom', 3, '188888888888'); INSERT INTO `user` VALUES (2, 'Jerry', 'jerry', 4, '166666666666'); INSERT INTO `user` VALUES (3, 'Jock', '123456', 41, '188313284343'); INSERT INTO `user` VALUES (4, '传智播客', 'itcast', 15, '503320302323');
SET FOREIGN_KEY_CHECKS = 1;
|
2.创建一个SpringBoot引导项目,只需要勾选Mysql的相关模块,创建完成后添加如下依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.0</version> <relativePath/> </parent> <groupId>com.eldpepar</groupId> <artifactId>mp</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mp</name> <properties> <java.version>1.8</java.version> </properties> <dependencies>
<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.4.1</version> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.22</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
3.创建与数据库相对于的bean类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| package com.eldpepar.domain;
public class User { private Long id; private String name; private String password; private Integer age; private String tel;
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getTel() { return tel; }
public void setTel(String tel) { this.tel = tel; }
@Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", password='" + password + '\'' + ", age=" + age + ", tel='" + tel + '\'' + '}'; } }
|
4.编写dao层,这里不需要额外实现SQL语句,只需要继承BaseMapper,并且在泛型中填入bean类。最后加上@Mapper注解即可完成
1 2 3 4 5 6 7 8 9 10
| package com.eldpepar.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.eldpepar.domain.User; import org.apache.ibatis.annotations.Mapper;
@Mapper public interface UserDao extends BaseMapper<User> {
}
|
分页查询
1.设置分页拦截器作为Spring管理bean
1 2 3 4 5 6 7 8 9 10
| @Configuration public class MpConfig {
@Bean public MybatisPlusInterceptor pageInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }
|
2.执行分页查询
1 2 3 4 5 6 7 8 9 10
| ```@Test void testPageSelect() { IPage page = new Page(2, 3); userDao.selectPage(page, null); System.out.println("当前页码:" + page.getCurrent()); System.out.println("每页总数据量:" + page.getSize()); System.out.println("总页数:" + page.getPages()); System.out.println("数据总量:" + page.getTotal()); System.out.println("当前页数据:" + page.getRecords()); }
|
如果需要查看查询日志,需要在yml文件中开启相关功能
1 2 3 4
| mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
条件查询
MybaitsPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合
1.格式一:常规格式(支持链式)
1 2 3 4 5 6 7 8
| @Test void selectWrapper() { QueryWrapper<User> qw = new QueryWrapper<>(); qw.le("age", 65).ge("age", 18); List<User> users = userDao.selectList(qw); System.out.println(users); }
|
2.格式二:lambda格式(常规查询)
1 2 3 4 5 6 7 8
| @Test void selectLambdaWrapper() { QueryWrapper<User> qw = new QueryWrapper<>(); //查询年龄大于18,小于65的 qw.lambda().lt(User::getAge, 65).ge(User::getAge, 18); List<User> users = userDao.selectList(qw); System.out.println(users); }
|
3.格式三:lambda格式(专属查询)
1 2 3 4 5 6 7 8 9
| @Test void selectLambdaLambdaWrapper() { LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>(); lqw.lt(User::getAge, 18).or().ge(User::getAge, 30); List<User> users = userDao.selectList(lqw); System.out.println(users); }
|
null值处理
如果没有导入lombok相关的依赖先导入lombok依赖,在idea高版本继承了lombok插件,不需要额外安装lombok插件,如果是低版本还需要安装lombok插件
1 2 3 4 5 6 7
| <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <scope>provided</scope> </dependency>
|
设置一个类用来规定age的最大值
1 2 3 4
| @Data public class UserQuery extends User { private Integer ageMax; }
|
执行条件查询,如果其中一个条件不存在,则会绕过这个条件
1 2 3 4 5 6 7 8 9 10 11
| @Test void selectByNull() { LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper(); UserQuery userQuery = new UserQuery(); userQuery.setAge(10); lqw.ge(null != userQuery.getAge(), User::getAge, userQuery.getAge()); lqw.lt(null != userQuery.getAgeMax(), User::getAge, userQuery.getAgeMax()); List<User> users = userDao.selectList(lqw); System.out.println(users); }
|
查询投影
1.查询结果包含模型中部分属性
1 2 3 4 5 6 7
| @Test void selectByAtt() { LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>(); lqw.select(User::getId, User::getName, User::getAge); List<User> users = userDao.selectList(lqw); System.out.println(users); }
|
2.查询结果包含模型中未定义的属性
1 2 3 4 5 6 7 8
| @Test void selectByNotAtt() { QueryWrapper<User> qm = new QueryWrapper<>(); qm.select("count(*) as num,tel"); qm.groupBy("tel"); List<Map<String, Object>> maps = userDao.selectMaps(qm); System.out.println(maps); }
|
条件设置
通常在不同的需求中,需要设置不同的查询条件下面列出了一些常见的查询条件
1.用户登录(eq匹配)
1 2 3 4
| LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>(); lqw.eq(User::getName, userQuery.getName()).eq(User::getPassword, userQuery.getPassword()); User loginUser = userDao.selectOne(lqw); System.out.println(loginUser);
|
2.购物设定价格区间、户籍设定年龄区间(le,ge匹配或between匹配)
1 2 3 4 5 6 7
| LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
lqw.le(User::getAge,userQuery.getAge()).eq(User::getAge,userQuery.getAgeMax());
lqw.between(User::getAge,userQuery.getAge(),userQuery.getAgeMax()); List<User> userList = userDao.selectList(lqw); System.out.println(userList);
|
3.查信息,搜索新闻(非全文检索:like匹配)
1 2 3 4
| LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>(); lqw.likeLeft(User::getTel, userQuery.getTel()); List<User> userList = userDao.selectList(lqw); System.out.println(userList);
|
4.统计报表(分组查询聚合函数)
1 2 3 4 5
| QueryWrapper<User> qw = new QueryWrapper<>(); qw.select("gender", "count(*) as nums"); qw.groupBy("gender"); List<Map<String, Object>> maps = userDao.selectMaps(qw); System.out.println(maps);
|
映射匹配
如果表名或者是列名与数据库中的不同,就需要进行映射匹配,可以通过@TableName设置对应的表明,@TableField设置对应的列名以及其他的属性
1 2 3 4 5 6 7 8 9 10 11 12
| @Data @TableName("tbl_user") public class IUser { private Long id; private String name; @TableField(value = "pwd",select = false) private String password; private Integer age; private String tel; @TableField(exist = false) private Integer online; }
|
其中select值为false表示的是此列不查询,exist值为false表示该列在数据库中不存在
ID生成策略
可以通过@TableId注解来设置,type值用来设置ID生成策略,常见的Id生成策略有AUTO、雪花、UUID等。雪花算法是一个64位的二进制组成,包括一位占位符、41位时间戳、10位机器码、以及12位序列号组成
1.AUTO使用数据库id自增策略控制id生成
2.NONE不设置id生成策略
3.INPUT用户手工输入id
4.ASSIGN_ID雪花算法生成id(可兼容数值类型与字符串型)
5.ASSIGN_UUID以UUID生成算法作为id生成策略
1 2 3 4
| public class User { TableId(type = IdType.AUTO) private Long id; }
|
全局配置
可以全局配置表名的前缀后缀等,大大的简化开发过程
1 2 3 4
| mybatis-plus: global-config: db-config: table-prefix: tbl_
|
多记录操作
1.按主键删除多条记录
1 2
| List<Long> ids = Arrays.asList(new Long[]{2,3}); userDao.deleteBatchIds(ids);
|
2.按主键查询多条记录
1 2
| List<Long> ids = Arrays.asList(new Long[]{2,3}); List<User> userList = userDao.selectBatchIds(ids);
|
逻辑删除
为数据设置是否可用状态字段,删除时设置对待他字段为不可用状态,数据保留在数据库中
1.首先在数据库中添加一个长度为一的字段delted,并且设置默认值为0表示没有表删除
2.在bean类中添加@TableLogic表示该字段是逻辑删除字段,并且设置value值和delval值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Data @TableName("tbl_user") public class IUser { private Long id; private String name; @TableField(value = "pwd",select = false) private String password; private Integer age; private String tel; @TableField(exist = false) private Integer online; @TableLogic(value = "0",delval = "1") private Integer delted; }
|
测试类
1 2 3 4 5
| @Test void testDelAndSelect() { iUserDao.deleteById(1L); System.out.println(iUserDao.selectList(null)); }
|
乐观锁
修改过程中会产生并发访问问题,可以使用乐观锁,可以解决较小的并发问题。乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
1.在数据库表中添加锁标记字段version
2.实体类中添加对应字段,并设置当前字段为乐观锁
1 2 3 4 5
| public class User { private Long id; @Version private Integer version; }
|
3.配置乐观锁拦截器实现锁机制对应的动态SQL语句拼装
1 2 3 4 5 6 7 8 9
| @Configuration public class MpConfig { @Bean public MybatisPlusInterceptor mpInterceptor() { MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor(); mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return mpInterceptor; } }
|
4.使用乐观锁机制在修改之前必须先获取到对应数据的version才可以正常进行
1 2 3 4 5 6 7 8
| @Test void testUpdate() { User user = userDao.selectById(1L); user.setName("Tom,...."); userDao.updateById(user); }
|