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的依赖:


  com.baomidou
  mybatis-plus-boot-starter
  3.4.0

完整依赖如下:



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.3.5.RELEASE
         
    
    com.tp
    demo-mp
    0.0.1-SNAPSHOT
    demo-mp
    Demo project for Spring Boot

    
        1.8
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            mysql
            mysql-connector-java
            runtime
        
        
        
            org.projectlombok
            lombok
            true 
        
        
        
            com.alibaba
            druid-spring-boot-starter
            1.2.1
        
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.0
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

配置数据库连接信息
server:
  port: 7269
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://localhost:3306/mybatis_plus_demo?useSSL=true&serverTimezone=GMT%2B8
      username: root
      password: tp123456
logging:
  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 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 {

}

接下来就可以测试啦,实际开发中我们应该写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:
 */
@SpringBootTest
public class MybatisPlusInsertTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * 插入1条数据,mp为我们提供了insert(T entity)方法
     * 该方法插入一条记录,返回影响行数
     * 

* 注意⚠️:MP的默认策略为:如果实体的某个属性为null,那么新增和修改时,会忽略null值字段 */ @Test void testInsert() { User user = new User(); user.setName("向东"); user.setAge(58); user.setManagerId(2); user.setEmail("[email protected]"); 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: 查询类测试
 */
@SpringBootTest
class MybatisPlusSelectTests {

    @Autowired
    private UserMapper userMapper;

    // ========================= 非条件构造器查询 =========================

    /**
     * SELECT id,name,age,email,manager_id,create_time FROM user
     */
    @Test
    void testSelectList() {
        List 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 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 queryMap = new HashMap<>();
        queryMap.put("name", "向北");
        queryMap.put("manager_id", 2); // 注意map的key为表的字段名,value为要查的字段值
        List 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 queryMap = new HashMap<>();
        queryMap.put("name", "向北");
        queryMap.put("manager_id", 2); // 注意map的key为表的字段名,value为要查的字段值
        queryMap.put("email", null);
        List 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 queryWrapper = new QueryWrapper<>();
        QueryWrapper queryWrapper = Wrappers.query();
        queryWrapper.eq("name", "张三").like("email", "163").lt("age", 40);
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", "雨").between("age", 20, 40).isNotNull("email");
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("name", "王").or().ge("age", 25).orderByDesc("age").orderByAsc("id");
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("name", "王").and(qw -> qw.lt("age", 40).or().isNotNull("email"));
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.likeRight("name", "王").
                or(qw -> qw.lt("age", 40).gt("age", 20).isNotNull("email"));
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.nested(wp -> wp.lt("age", 40).or().isNotNull("email")).likeRight("name", "王");
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.in("age", Arrays.asList(31, 32, 34, 35));
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.in("age", Arrays.asList(31, 32, 34, 35)).last("limit 1"); // last会无视优化,直接在sql后面拼接传入的语句
        List 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 queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "name", "age").lt("age", 40);
        // .select(String... columns)可以放在前面,也可以放在后面,例如下面注释内容
        // queryWrapper.lt("age", 40).select("id", "name", "age");
        List users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

    /**
     * 默认MP会查询实体全部字段,如果我们只想查询指定字段怎么办呢?
     * 查询指定列方式二:动态指定要查询的字段,更有利于查询实体类中多个字段,不想像方式一那样一个一个写的情形
     * ==>  Preparing: SELECT id,name,age,manager_id FROM user
     */
    @Test
    void testSelectByWrapper11() {
        QueryWrapper queryWrapper = new QueryWrapper<>();
        // 排除create_time和email字段,即不查询create_time和email字段
        queryWrapper.select(User.class, info -> !info.getColumn().equals("create_time") && !info.getColumn().equals("email"));
        List users = userMapper.selectList(queryWrapper);
        users.forEach(System.out::println);
    }

    /**
     * 关于condition
     * 在QueryWrapper的各个查询方法中,一般都会有重载的方法,例如like
     * 

* default Children like(R column, Object val) { * return this.like(true, column, val); * } *

* Children like(boolean condition, R column, Object val); *

* 其中有个重载的方法,前面需要传一个boolean类型的condition,它的含义是:如果 condition的值为true时,则添加后面的查询条件 * 例如我们做页面的列表,用户可输入多个查询条件,有值的就添加上查询条件 */ @Test void testSelectByWrapper12() { QueryWrapper 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 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 queryWrapper = new QueryWrapper<>(queryUser); List 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 queryWrapper = new QueryWrapper<>(); Map params = new HashMap<>(); params.put("name", "向东"); params.put("age", null); queryWrapper.allEq(params); List users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); // name = "向东" QueryWrapper queryWrapper2 = new QueryWrapper<>(); Map params2 = new HashMap<>(); params2.put("name", "向东"); params2.put("age", null); queryWrapper2.allEq(params2, false); List users2 = userMapper.selectList(queryWrapper2); users2.forEach(System.out::println); } /** * 查询返回一个map,map的key为数据库中的字段 * 应用场景1:当我们查询的字段不是所有字段,只是部分字段,如果我们用实体封装,那么实体中中未查询的字段就为空或者默认值,不优雅,这个时候可以用map接收指定查询的字段 * 应用场景2:当我们需要将数据库中的字段进行转换,或者使用函数时,这时候无法用实体封装查询结果,我们可以选择使用map */ @Test void testSelectMaps() { // 应用场景1 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "向东"); queryWrapper.select("name", "age"); // 只查询部分字段 List> result = userMapper.selectMaps(queryWrapper); result.forEach(System.out::println); //应用场景2 QueryWrapper 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> result2 = userMapper.selectMaps(queryWrapper2); result2.forEach(System.out::println); } /** * 根据Wrapper查询,查询全部记录 * 注意:只返回结果第一个字段的值 */ @Test void testSelectObjects() { // 应用场景1 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("id", "name").lt("age", 60); List objects = userMapper.selectObjs(queryWrapper); // 只会返回id,不会返回name {1,2,3,4,5,6,7,8} objects.forEach(System.out::println); } /** * 根据查询条件进行统计总记录数 */ @Test void testSelectCount() { // 应用场景1 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lt("age", 60); Integer count = userMapper.selectCount(queryWrapper); System.out.println(count); } /** * 查询1条结果,结果必须为1条或0条 * 如果数据库存在多条会报错 */ @Test void testSelectOne() { // 应用场景1 QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("id", 1); User user = userMapper.selectOne(queryWrapper); System.out.println(user); } // ========================= Lambda条件构造器查询 ========================= /** * Lambda条件构造器查询能有效防止我们手写数据库字段写错问题 */ @Test void testSelectLambda1() { // 创建Lambda条件构造器的方式有3种: LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper lambdaQueryWrapper1 = Wrappers.lambdaQuery(); LambdaQueryWrapper lambdaQueryWrapper2 = new QueryWrapper().lambda(); // User::getNamed代表要查询name这个列,lambdaQueryWrapper的好处是避免手写要查询字段字符串,如果手写的也数据库不一致造成报错问题 lambdaQueryWrapper.eq(User::getName, "向东").lt(User::getAge, 80); List users = userMapper.selectList(lambdaQueryWrapper); users.forEach(System.out::println); } @Test void testSelectLambda2() { // 创建Lambda条件构造器的方式有3种: LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper lambdaQueryWrapper1 = Wrappers.lambdaQuery(); LambdaQueryWrapper lambdaQueryWrapper2 = new QueryWrapper().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 users = userMapper.selectList(lambdaQueryWrapper); users.forEach(System.out::println); } /** * LambdaQueryChainWrapper,这个可以再次简化写法,可以直接调用.list() 或者 .one() 返回查询结果 */ @Test void testSelectLambdaQueryChainWrapper() { // 创建Lambda条件构造器的方式有3种: LambdaQueryChainWrapper lambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(userMapper); List 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:
 */
@SpringBootTest
class MybatisPlusUpdateTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * UpdateById
     * 根据主键ID修改实体信息的方法
     * 此更新会忽略实体null值,不会更新实体中属性值为null对应的字段
     */
    @Test
    void testUpdateById() {
        User user = new User();
        user.setId(8);
        user.setEmail("[email protected]");
        userMapper.updateById(user);
    }

    /**
     * 利用UpdateWrapper更新实体>>>>空参构造器:UpdateWrapper updateWrapper = new UpdateWrapper<>();
     * UpdateWrapper的条件会出现在where条件中
     * 实体不为空的信息是要更新的字段
     */
    @Test
    void testUpdateByWrapper() {
        // UpdateWrapper的条件会出现在where条件中
        UpdateWrapper updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("name", "李艺伟");
        updateWrapper.eq("age", 28);

        // 实体不为空的信息是要更新的字段
        User user = new User();
        user.setEmail("[email protected]");
        user.setManagerId(1);

        // 返回影响行数
        int rows = userMapper.update(user, updateWrapper);
        System.out.println("影响行数:" + rows);

    }

    /**
     * 利用UpdateWrapper更新实体>>>>带参构造器:UpdateWrapper updateWrapper = new UpdateWrapper<>(whereUser);
     * 这时候updateWrapper中会将whereUser这个实体中不为空的属性设置为where查询条件
     * 注意:这个时候whereUser实体的查询条件和后续updateWrapper调用查询方法时指定的查询条件会同时生效,如果存在相同查询条件,查询条件会出现2次
     */
    @Test
    void testUpdateByWrapper2() {
        // 通过实体构造查询条件
        User whereUser = new User();
        whereUser.setName("李艺伟");
        whereUser.setAge(28);
        UpdateWrapper updateWrapper = new UpdateWrapper<>(whereUser);
        // updateWrapper.eq("manager_id", 1); // 可以继续添加查询条件

        // 实体不为空的信息是要更新的字段
        User user = new User();
        user.setEmail("[email protected]");
        user.setManagerId(2);

        // 返回影响行数
        int rows = userMapper.update(user, updateWrapper);
        System.out.println("影响行数:" + rows);

    }

    /**
     * 利用UpdateWrapper更新实体>>>>带参构造器:UpdateWrapper updateWrapper = new UpdateWrapper<>(whereUser);
     * 如果我们更新的字段很少,例如实体中我们只更新1、2个字段,如果像上面的更新还需要创建一个对象,这样有点不优雅
     * 又或者我们的需求是想把某个字段设置为null
     * 这时候我们可以使用UpdateWrapper的set方法,指定设置数据库表中具体哪个字段设置为什么值
     */
    @Test
    void testUpdateByWrapper3() {
        // 通过实体构造查询条件
        User whereUser = new User();
        whereUser.setName("李艺伟");
        whereUser.setAge(28);
        UpdateWrapper 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 lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(User::getName, "李艺伟").set(User::getAge, 30).set(User::getEmail, "[email protected]");
        // 返回影响行数
        int rows = userMapper.update(null, lambdaUpdateWrapper);
        System.out.println("影响行数:" + rows);
    }

    /**
     * 同理,UpdateWrapper同样支持LambdaChain形式
     * 用法类似LambdaQueryChainWrapper
     * 但其返回值不是影响行数,而是boolean值,标识更新成功或失败
     */
    @Test
    void testUpdateByWrapperLambdaChain() {
        // 构造LambdaUpdateWrapper
        LambdaUpdateChainWrapper chainWrapper = new LambdaUpdateChainWrapper<>(userMapper);
        boolean result = chainWrapper
                .eq(User::getName, "李艺伟") // 设置查询条件
                .set(User::getAge, 31).set(User::getEmail, "[email protected]") //设置要更新的内容
                .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:
 */
@SpringBootTest
class 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 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 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 queryWrapper = Wrappers.query(user);
        int rows = userMapper.delete(queryWrapper);
        System.out.println("影响记录数:" + rows);
    }

    /**
     * 根据LambdaQueryWrapper条件构造器删除
     */
    @Test
    void testDeleteByLambdaQueryWrapper() {
        LambdaQueryWrapper 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 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管理即可
 */
@Configuration
public 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分页测试
 */
@SpringBootTest
class MybatisPlusPageTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * 分页,结果采用实体封装
     */
    @Test
    void testPage1() {
        Page userPage = new Page<>(1, 10); //当前页为第1页,每页显示10条
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("age", 80);
        Page pageResult = userMapper.selectPage(userPage, queryWrapper);
        System.out.println("总页数:" + pageResult.getPages());
        System.out.println("总记录数:" + pageResult.getTotal());
        List users = pageResult.getRecords();
        users.forEach(System.out::println);
    }

    /**
     * 分页,结果采用Map封装,key为列名或者列别名,value为值
     */
    @Test
    void testPage2() {
        Page> userPage = new Page<>(1, 10); //当前页为第1页,每页显示10条
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("age", 80).select("name", "age");
        Page> pageResult = userMapper.selectMapsPage(userPage, queryWrapper);
        System.out.println("总页数:" + pageResult.getPages());
        System.out.println("总记录数:" + pageResult.getTotal());
        List> users = pageResult.getRecords();
        users.forEach(System.out::println);
    }
}

你可能感兴趣的:(Mybatis-Plus极速入门)