Mybatis-Plus极速入门
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
支持数据库
mysql 、mariadb 、oracle 、db2 、h2 、hsql 、sqlite 、postgresql 、sqlserver 、presto 、Gauss 、Firebird
Phoenix 、clickhouse 、Sybase ASE 、 OceanBase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库 、
框架结构
framework
快速开始
以springboot项目为例
引入mybatisPlus的依赖:
<!-- mybatis-plus --><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version></dependency>
完整依赖如下:
<?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.3.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.tp</groupId> <artifactId>demo-mp</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo-mp</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <!-- web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 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.1</version> </dependency> <!-- mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> <!-- test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>
配置数据库连接信息
server: port: 7269spring: datasource: type: com.alibaba.druid.pool.DruidDataSource druid: url: jdbc:mysql://localhost:3306/mybatis_plus_demo?useSSL=true&serverTimezone=GMT%2B8 username: root password: tp123456logging: level: root: info com.tp: debug
创建一个数据库表
SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for USER-- ----------------------------DROP TABLE IF EXISTS `USER`;CREATE TABLE `USER` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `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 '邮箱', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;SET FOREIGN_KEY_CHECKS = 1;
项目中创建实体User.java
@Data @TableName("user")public class User { @TableId(value = "id", type = IdType.AUTO) private Integer id; /** 姓名 */ private String name; /** 年龄 */ private Integer age; /** 邮箱 */ private String email; /** 直属上级ID */ private Integer managerId; /** 创建时间 */ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //此注解用来接收字符串类型的参数封装成LocalDateTime类型 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") //此注解将date类型数据转成字符串响应出去 private LocalDateTime createTime; /** 对于数据库中没有的字段,如果我们不处理,在新增或修改的时候会出现错误,mp为我们提供了注解@TableField解决此类问题 */ @TableField(exist = false) // exist = false标识数据库没有此字段,告诉mp映射时忽略此字段,防止出现错误,默认为true List<Integer> roleIds; }
注意:对于数据库中没有的字段,如果我们不做特殊处理,我们在操作数据库时MP会给我们自动进行映射,但是因为数据库中并没有这个字段,这样就会报错:
org.springframework.jdbc.BadSqlGrammarException: ### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column 'role_ids' in 'field list'
针对这种情形,我们可以使用MP提供的注解@TableField(exist = false)
来表明某个字段不是数据库的字段,其中exist表示是否存在,默认为true
创建Mapper,继承自MP给我提供的BaseMapper
package com.tp.demo.mp.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.tp.demo.mp.entity.User;/** * FileName: UserMapper * Author: TP * Description: 用户服务Mapper */public interface UserMapper extends BaseMapper<User> {}
接下来就可以测试啦,实际开发中我们应该写Service,但是这里为了方便,就不写了
常用增删改查
新增:
package com.tp.demo.mp;import com.tp.demo.mp.entity.User;import com.tp.demo.mp.mapper.UserMapper;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDateTime;/** * FileName: MybatisPlusInsertTests * Author: TP * Description: */@SpringBootTestpublic class MybatisPlusInsertTests { @Autowired private UserMapper userMapper; /** * 插入1条数据,mp为我们提供了insert(T entity)方法 * 该方法插入一条记录,返回影响行数 * <p> * 注意⚠️:MP的默认策略为:如果实体的某个属性为null,那么新增和修改时,会忽略null值字段 */ @Test void testInsert() { User user = new User(); user.setName("向东"); user.setAge(58); user.setManagerId(2); user.setEmail("xb@163.com"); user.setCreateTime(LocalDateTime.now()); int rows = userMapper.insert(user); System.out.println("影响记录数:" + rows); System.out.println("新记录的主键ID:" + user.getId()); }}
MP为我们提供了insert(T entity)方法,该方法插入一条记录,返回影响行数,MP的默认策略为:如果实体的某个属性为null,那么新增和修改时,会忽略null值字段,如果你想获取新增的实体的ID,可以直接调用实体的getId方法获取。
查询
package com.tp.demo.mp;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.toolkit.Wrappers;import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;import com.tp.demo.mp.entity.User;import com.tp.demo.mp.mapper.UserMapper;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;import java.util.Map;/** * FileName: MybatisPlusSelectTests * Author: TP * Description: 查询类测试 */@SpringBootTestclass MybatisPlusSelectTests { @Autowired private UserMapper userMapper; // ========================= 非条件构造器查询 ========================= /** * SELECT id,name,age,email,manager_id,create_time FROM user */ @Test void testSelectList() { List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } /** * SELECT id,name,age,email,manager_id,create_time FROM user WHERE id=? */ @Test void testSelectById() { User user = userMapper.selectById(1); System.out.println(user); } /** * SELECT id,name,age,email,manager_id,create_time FROM user WHERE id IN ( ? , ? ) */ @Test void testSelectBatchIds() { List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 3)); users.forEach(System.out::println); } /** * SELECT id,name,age,email,manager_id,create_time FROM user WHERE manager_id = ? AND name = ? */ @Test void testSelectByMap() { Map<String, Object> queryMap = new HashMap<>(); queryMap.put("name", "向北"); queryMap.put("manager_id", 2); // 注意map的key为表的字段名,value为要查的字段值 List<User> users = userMapper.selectByMap(queryMap); users.forEach(System.out::println); } /** * Map查询,查询条件值为null的不会被忽略 * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE manager_id = ? AND name = ? AND email IS NULL * ==> Parameters: 2(Integer), 向北(String) */ @Test void testSelectByMap2() { Map<String, Object> queryMap = new HashMap<>(); queryMap.put("name", "向北"); queryMap.put("manager_id", 2); // 注意map的key为表的字段名,value为要查的字段值 queryMap.put("email", null); List<User> users = userMapper.selectByMap(queryMap); users.forEach(System.out::println); } // ========================= Wrapper条件构造器查询 ========================= /** * 通过条件构造器查询 * 名字为"张三",邮箱包含163,并且年龄<40 * Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name = ? AND email LIKE ? AND age < ?) * Parameters: 张三(String), %163%(String), 40(Integer) */ @Test void testSelectByWrapper() { // MP提供了2种创建QueryWrapper的方法: // QueryWrapper<User> queryWrapper = new QueryWrapper<>(); QueryWrapper<User> queryWrapper = Wrappers.query(); queryWrapper.eq("name", "张三").like("email", "163").lt("age", 40); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 名字中包含"雨",并且年龄大于等于20且小于等于40,并且email不为空 * Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL) * Parameters: %雨%(String), 20(Integer), 40(Integer) */ @Test void testSelectByWrapper2() { // MP提供了2种创建QueryWrapper的方法: QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.like("name", "雨").between("age", 20, 40).isNotNull("email"); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同时按照id升序排列 * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? OR age >= ?) ORDER BY age DESC,id ASC * ==> Parameters: 王%(String), 25(Integer) */ @Test void testSelectByWrapper3() { // MP提供了2种创建QueryWrapper的方法: QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.likeRight("name", "王").or().ge("age", 25).orderByDesc("age").orderByAsc("id"); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 名字为王姓,并且(年龄<40或邮箱为空) * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? AND (age < ? OR email IS NOT NULL)) * ==> Parameters: 王%(String), 40(Integer) */ @Test void testSelectByWrapper4() { // MP提供了2种创建QueryWrapper的方法: QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.likeRight("name", "王").and(qw -> qw.lt("age", 40).or().isNotNull("email")); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 字为王姓,或者(年龄<40并且年龄>20并且邮箱不为空) * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (name LIKE ? OR (age < ? AND age > ? AND email IS NOT NULL)) * ==> Parameters: 王%(String), 40(Integer), 20(Integer) */ @Test void testSelectByWrapper5() { // MP提供了2种创建QueryWrapper的方法: QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.likeRight("name", "王"). or(qw -> qw.lt("age", 40).gt("age", 20).isNotNull("email")); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * (年龄<40或者邮箱不为空)并且姓名为王姓 * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE ((age < ? OR email IS NOT NULL) AND name LIKE ?) * ==> Parameters: 40(Integer), 王%(String) */ @Test void testSelectByWrapper7() { // MP提供了2种创建QueryWrapper的方法: QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.nested(wp -> wp.lt("age", 40).or().isNotNull("email")).likeRight("name", "王"); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 年龄在(31,32,34,45)中的 * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (age IN (?,?,?,?)) * ==> Parameters: 31(Integer), 32(Integer), 34(Integer), 35(Integer) */ @Test void testSelectByWrapper8() { // MP提供了2种创建QueryWrapper的方法: QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.in("age", Arrays.asList(31, 32, 34, 35)); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 返回满足条件的其中一条记录即可 * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE (age IN (?,?,?,?)) limit 1 * ==> Parameters: 31(Integer), 32(Integer), 34(Integer), 35(Integer) */ @Test void testSelectByWrapper9() { // MP提供了2种创建QueryWrapper的方法: QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.in("age", Arrays.asList(31, 32, 34, 35)).last("limit 1"); // last会无视优化,直接在sql后面拼接传入的语句 List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 默认MP会查询实体全部字段,如果我们只想查询指定字段怎么办呢? * 查询指定列方式一:指定要查询的字段 * ==> Preparing: SELECT id,name,age FROM user WHERE (age < ?) * ==> Parameters: 40(Integer) */ @Test void testSelectByWrapper10() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.select("id", "name", "age").lt("age", 40); // .select(String... columns)可以放在前面,也可以放在后面,例如下面注释内容 // queryWrapper.lt("age", 40).select("id", "name", "age"); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 默认MP会查询实体全部字段,如果我们只想查询指定字段怎么办呢? * 查询指定列方式二:动态指定要查询的字段,更有利于查询实体类中多个字段,不想像方式一那样一个一个写的情形 * ==> Preparing: SELECT id,name,age,manager_id FROM user */ @Test void testSelectByWrapper11() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); // 排除create_time和email字段,即不查询create_time和email字段 queryWrapper.select(User.class, info -> !info.getColumn().equals("create_time") && !info.getColumn().equals("email")); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 关于condition * 在QueryWrapper的各个查询方法中,一般都会有重载的方法,例如like * <p> * default Children like(R column, Object val) { * return this.like(true, column, val); * } * <p> * Children like(boolean condition, R column, Object val); * <p> * 其中有个重载的方法,前面需要传一个boolean类型的condition,它的含义是:如果 condition的值为true时,则添加后面的查询条件 * 例如我们做页面的列表,用户可输入多个查询条件,有值的就添加上查询条件 */ @Test void testSelectByWrapper12() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); boolean condition = (int) (Math.random() * 100) % 2 == 1; System.out.println(condition); queryWrapper .lt("age", 40) .eq(condition, "name", "张三"); //如果condition为false时,不会添加查询条件:and name = "张三" List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 我们可以通过一个实体构造一个queryWrapper,MP默认会将实体属性中值不为空的作为查询条件,用and连接生成sql * ==> Preparing: SELECT id,name,age,email,manager_id,create_time FROM user WHERE name=? AND age=? * ==> Parameters: 向东(String), 58(Integer) */ @Test void testSelectByEntity() { User queryUser = new User(); queryUser.setName("向东"); queryUser.setAge(58); QueryWrapper<User> queryWrapper = new QueryWrapper<>(queryUser); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } /** * 调用queryWrapper.allEq(params) 时,params中的null值会被翻译成:字段名 is null * 调用queryWrapper.allEq(params,false)时,params中的null值会被忽略 */ @Test void testAllEq() { // name = "向东" and age is null QueryWrapper<User> queryWrapper = new QueryWrapper<>(); Map<String, Object> params = new HashMap<>(); params.put("name", "向东"); params.put("age", null); queryWrapper.allEq(params); List<User> users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); // name = "向东" QueryWrapper<User> queryWrapper2 = new QueryWrapper<>(); Map<String, Object> params2 = new HashMap<>(); params2.put("name", "向东"); params2.put("age", null); queryWrapper2.allEq(params2, false); List<User> users2 = userMapper.selectList(queryWrapper2); users2.forEach(System.out::println); } /** * 查询返回一个map,map的key为数据库中的字段 * 应用场景1:当我们查询的字段不是所有字段,只是部分字段,如果我们用实体封装,那么实体中中未查询的字段就为空或者默认值,不优雅,这个时候可以用map接收指定查询的字段 * 应用场景2:当我们需要将数据库中的字段进行转换,或者使用函数时,这时候无法用实体封装查询结果,我们可以选择使用map */ @Test void testSelectMaps() { // 应用场景1 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "向东"); queryWrapper.select("name", "age"); // 只查询部分字段 List<Map<String, Object>> result = userMapper.selectMaps(queryWrapper); result.forEach(System.out::println); //应用场景2 QueryWrapper<User> queryWrapper2 = new QueryWrapper<>(); queryWrapper2 .select("avg(age) avg_age", "min(age) min_age", "max(age) max_age", "manager_id") // 计算查询 .groupBy("manager_id").having("sum(age)<{0}", 50); List<Map<String, Object>> result2 = userMapper.selectMaps(queryWrapper2); result2.forEach(System.out::println); } /** * 根据Wrapper查询,查询全部记录 * 注意:只返回结果第一个字段的值 */ @Test void testSelectObjects() { // 应用场景1 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.select("id", "name").lt("age", 60); List<Object> objects = userMapper.selectObjs(queryWrapper); // 只会返回id,不会返回name {1,2,3,4,5,6,7,8} objects.forEach(System.out::println); } /** * 根据查询条件进行统计总记录数 */ @Test void testSelectCount() { // 应用场景1 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.lt("age", 60); Integer count = userMapper.selectCount(queryWrapper); System.out.println(count); } /** * 查询1条结果,结果必须为1条或0条 * 如果数据库存在多条会报错 */ @Test void testSelectOne() { // 应用场景1 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("id", 1); User user = userMapper.selectOne(queryWrapper); System.out.println(user); } // ========================= Lambda条件构造器查询 ========================= /** * Lambda条件构造器查询能有效防止我们手写数据库字段写错问题 */ @Test void testSelectLambda1() { // 创建Lambda条件构造器的方式有3种: LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<User> lambdaQueryWrapper1 = Wrappers.lambdaQuery(); LambdaQueryWrapper lambdaQueryWrapper2 = new QueryWrapper<User>().lambda(); // User::getNamed代表要查询name这个列,lambdaQueryWrapper的好处是避免手写要查询字段字符串,如果手写的也数据库不一致造成报错问题 lambdaQueryWrapper.eq(User::getName, "向东").lt(User::getAge, 80); List<User> users = userMapper.selectList(lambdaQueryWrapper); users.forEach(System.out::println); } @Test void testSelectLambda2() { // 创建Lambda条件构造器的方式有3种: LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<User> lambdaQueryWrapper1 = Wrappers.lambdaQuery(); LambdaQueryWrapper lambdaQueryWrapper2 = new QueryWrapper<User>().lambda(); // where name like %王% and (age < 80 or email is not null) lambdaQueryWrapper.likeRight(User::getName, "王").and(lqw -> lqw.lt(User::getAge, 40).or().isNotNull(User::getEmail)); List<User> users = userMapper.selectList(lambdaQueryWrapper); users.forEach(System.out::println); } /** * LambdaQueryChainWrapper,这个可以再次简化写法,可以直接调用.list() 或者 .one() 返回查询结果 */ @Test void testSelectLambdaQueryChainWrapper() { // 创建Lambda条件构造器的方式有3种: LambdaQueryChainWrapper<User> lambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(userMapper); List<User> users = lambdaQueryChainWrapper .likeRight(User::getName, "王") .and(lqw -> lqw.lt(User::getAge, 40).or().isNotNull(User::getEmail)) .list(); // 可以直接调用.list() 或者 .one() 返回查询结果 users.forEach(System.out::println); }}
修改
package com.tp.demo.mp;import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;import com.tp.demo.mp.entity.User;import com.tp.demo.mp.mapper.UserMapper;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;/** * FileName: MybatisPlusUpdateTests * Author: TP * Description: */@SpringBootTestclass MybatisPlusUpdateTests { @Autowired private UserMapper userMapper; /** * UpdateById * 根据主键ID修改实体信息的方法 * 此更新会忽略实体null值,不会更新实体中属性值为null对应的字段 */ @Test void testUpdateById() { User user = new User(); user.setId(8); user.setEmail("xd@163.com"); userMapper.updateById(user); } /** * 利用UpdateWrapper更新实体>>>>空参构造器:UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); * UpdateWrapper的条件会出现在where条件中 * 实体不为空的信息是要更新的字段 */ @Test void testUpdateByWrapper() { // UpdateWrapper的条件会出现在where条件中 UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(); updateWrapper.eq("name", "李艺伟"); updateWrapper.eq("age", 28); // 实体不为空的信息是要更新的字段 User user = new User(); user.setEmail("lyw@126.com"); user.setManagerId(1); // 返回影响行数 int rows = userMapper.update(user, updateWrapper); System.out.println("影响行数:" + rows); } /** * 利用UpdateWrapper更新实体>>>>带参构造器:UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser); * 这时候updateWrapper中会将whereUser这个实体中不为空的属性设置为where查询条件 * 注意:这个时候whereUser实体的查询条件和后续updateWrapper调用查询方法时指定的查询条件会同时生效,如果存在相同查询条件,查询条件会出现2次 */ @Test void testUpdateByWrapper2() { // 通过实体构造查询条件 User whereUser = new User(); whereUser.setName("李艺伟"); whereUser.setAge(28); UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser); // updateWrapper.eq("manager_id", 1); // 可以继续添加查询条件 // 实体不为空的信息是要更新的字段 User user = new User(); user.setEmail("lyw@qq.com"); user.setManagerId(2); // 返回影响行数 int rows = userMapper.update(user, updateWrapper); System.out.println("影响行数:" + rows); } /** * 利用UpdateWrapper更新实体>>>>带参构造器:UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser); * 如果我们更新的字段很少,例如实体中我们只更新1、2个字段,如果像上面的更新还需要创建一个对象,这样有点不优雅 * 又或者我们的需求是想把某个字段设置为null * 这时候我们可以使用UpdateWrapper的set方法,指定设置数据库表中具体哪个字段设置为什么值 */ @Test void testUpdateByWrapper3() { // 通过实体构造查询条件 User whereUser = new User(); whereUser.setName("李艺伟"); whereUser.setAge(28); UpdateWrapper<User> updateWrapper = new UpdateWrapper<>(whereUser); updateWrapper.set("age", 29).set("email", null); // 返回影响行数 int rows = userMapper.update(null, updateWrapper); System.out.println("影响行数:" + rows); } /** * UpdateWrapper同样支持Lambda形式,用法类似LambdaQueryWrapper */ @Test void testUpdateByWrapperLambda() { // 构造LambdaUpdateWrapper LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); lambdaUpdateWrapper.eq(User::getName, "李艺伟").set(User::getAge, 30).set(User::getEmail, "lyw@163.com"); // 返回影响行数 int rows = userMapper.update(null, lambdaUpdateWrapper); System.out.println("影响行数:" + rows); } /** * 同理,UpdateWrapper同样支持LambdaChain形式 * 用法类似LambdaQueryChainWrapper * 但其返回值不是影响行数,而是boolean值,标识更新成功或失败 */ @Test void testUpdateByWrapperLambdaChain() { // 构造LambdaUpdateWrapper LambdaUpdateChainWrapper<User> chainWrapper = new LambdaUpdateChainWrapper<>(userMapper); boolean result = chainWrapper .eq(User::getName, "李艺伟") // 设置查询条件 .set(User::getAge, 31).set(User::getEmail, "lyw@chain.com") //设置要更新的内容 .update(); //需要调用update(),执行更新 System.out.println("更新是否成功:" + result); }}
删除
package com.tp.demo.mp;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.toolkit.Wrappers;import com.tp.demo.mp.entity.User;import com.tp.demo.mp.mapper.UserMapper;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.Map;/** * FileName: MybatisPlusDeleteTests * Author: TP * Description: */@SpringBootTestclass MybatisPlusDeleteTests { @Autowired private UserMapper userMapper; /** * 根据ID单个删除 */ @Test void testDeleteById() { int rows = userMapper.deleteById(8); System.out.println("影响记录数:" + rows); } /** * 根据ID批量删除 */ @Test void testDeleteBatchIds() { int rows = userMapper.deleteBatchIds(Arrays.asList(9, 10)); System.out.println("影响记录数:" + rows); } /** * 根据Map,map中的元素会作为查询条件且等值and连接 */ @Test void testDeleteByMap() { Map<String, Object> map = new HashMap<>(); map.put("name", "向东"); map.put("age", 31); map.put("manager_id", null); int rows = userMapper.deleteByMap(map); System.out.println("影响记录数:" + rows); } /** * 根据QueryWrapper条件构造器删除 */ @Test void testDeleteByWrapper() { QueryWrapper<User> queryWrapper = Wrappers.query(); queryWrapper.eq("name", "向东"); queryWrapper.eq("age", "31"); int rows = userMapper.delete(queryWrapper); System.out.println("影响记录数:" + rows); } /** * 根据QueryWrapper条件构造器,通过指定一个实体删除 */ @Test void testDeleteByWrapper2() { User user = new User(); user.setName("向东"); user.setAge(31); QueryWrapper<User> queryWrapper = Wrappers.query(user); int rows = userMapper.delete(queryWrapper); System.out.println("影响记录数:" + rows); } /** * 根据LambdaQueryWrapper条件构造器删除 */ @Test void testDeleteByLambdaQueryWrapper() { LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery(); // DELETE FROM user WHERE (name = ? OR age >= ?) lambdaQueryWrapper.eq(User::getName, "向东").or().ge(User::getAge, 60); int rows = userMapper.delete(lambdaQueryWrapper); System.out.println("影响记录数:" + rows); } /** * 根据LambdaQueryWrapper条件构造器,通过指定一个实体删除 */ @Test void testDeleteByLambdaQueryWrapper2() { User user = new User(); user.setName("向东"); user.setAge(50); LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery(user); int rows = userMapper.delete(lambdaQueryWrapper); System.out.println("影响记录数:" + rows); }}
Mybatis-Plus分页
Mybatis-Plus为我们提供了非常方便的分页插件,用法:
package com.tp.demo.mp.config;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * FileName: MybatisPlusPageConfig * Author: TP * Description: 使用mybatisPlus的分页插件 * 只需要提供一个PaginationInnerInterceptor交给Spring管理即可 */@Configurationpublic class MybatisPlusPageConfig { @Bean public PaginationInnerInterceptor paginationInnerInterceptor(){ return new PaginationInnerInterceptor(); }}
测试:
package com.tp.demo.mp;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.tp.demo.mp.entity.User;import com.tp.demo.mp.mapper.UserMapper;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import java.util.List;import java.util.Map;/** * FileName: MybatisPlusPageTests * Author: TP * Description: mybatisPlus分页测试 */@SpringBootTestclass MybatisPlusPageTests { @Autowired private UserMapper userMapper; /** * 分页,结果采用实体封装 */ @Test void testPage1() { Page<User> userPage = new Page<>(1, 10); //当前页为第1页,每页显示10条 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.lt("age", 80); Page<User> pageResult = userMapper.selectPage(userPage, queryWrapper); System.out.println("总页数:" + pageResult.getPages()); System.out.println("总记录数:" + pageResult.getTotal()); List<User> users = pageResult.getRecords(); users.forEach(System.out::println); } /** * 分页,结果采用Map封装,key为列名或者列别名,value为值 */ @Test void testPage2() { Page<Map<String, Object>> userPage = new Page<>(1, 10); //当前页为第1页,每页显示10条 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.lt("age", 80).select("name", "age"); Page<Map<String, Object>> pageResult = userMapper.selectMapsPage(userPage, queryWrapper); System.out.println("总页数:" + pageResult.getPages()); System.out.println("总记录数:" + pageResult.getTotal()); List<Map<String, Object>> users = pageResult.getRecords(); users.forEach(System.out::println); }}
作者:Tian_Peng
链接:https://www.jianshu.com/p/ff59a6bebbd2