MyBatis-Plus笔记

一、MyBatis-Plus 核心优势

  1. 无侵入:只增强 MyBatis 功能,原有 MyBatis 代码不受任何影响,平滑迁移;
  2. 内置通用 Mapper:BaseMapper 封装单表增删改查,无需写 XML;
  3. 强大条件构造器:Wrapper 自动拼接动态 SQL,不用拼接字符串;
  4. 内置分页插件:一行代码实现分页,支持多数据库;
  5. 逻辑删除、乐观锁、主键策略开箱即用;
  6. 代码生成器:一键生成 Entity、Mapper、Service、Controller 全套代码;
  7. 支持多种数据库:MySQL、Oracle、PostgreSQL、SQLServer 等主流数据库。

二、SpringBoot 整合 MyBatis-Plus

2.1 Maven 依赖引入

xml

复制代码
<!-- SpringBoot 父工程自行引入 -->
<!-- MyBatis-Plus 启动器 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- 数据库连接池 HikariCP(SpringBoot默认) -->
<!-- lombok简化实体类get/set -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

2.2 application.yml 配置文件

yaml

复制代码
# 数据库配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 你的数据库密码

# MyBatis-Plus配置
mybatis-plus:
  # 实体类别名包路径
  type-aliases-package: com.example.mp.entity
  # mapper映射文件位置
  mapper-locations: classpath:mapper/*.xml
  configuration:
    # 开启SQL打印日志,开发调试必备
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 开启驼峰命名自动转换:数据库user_name → 实体userName
    map-underscore-to-camel-case: true
  global-config:
    db-config:
      # 主键自增策略
      id-type: auto
      # 逻辑删除字段名
      logic-delete-field: isDeleted
      logic-delete-value: 1 # 删除值
      logic-not-delete-value: 0 # 未删除值

2.3 启动类添加 Mapper 扫描注解

复制代码
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
// 扫描mapper接口所在包
@MapperScan("com.example.mp.mapper")
public class MpApplication {
    public static void main(String[] args) {
        SpringApplication.run(MpApplication.class, args);
    }
}

三、实体类、Mapper、Service 基础结构

3.1 数据库表设计(user 表)

复制代码
CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_name` varchar(30) DEFAULT NULL COMMENT '用户名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `version` int DEFAULT 1 COMMENT '乐观锁版本号',
  `is_deleted` tinyint DEFAULT 0 COMMENT '逻辑删除 0未删 1已删',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

3.2 实体类 User.java

使用 MP 注解映射表、字段,Lombok 简化代码

复制代码
package com.example.mp.entity;

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;

@Data
@TableName("user") // 映射数据库user表
public class User {
    // 主键自增
    @TableId(type = IdType.AUTO)
    private Long id;

    @TableField("user_name")
    private String userName;

    private Integer age;

    private String email;

    // 乐观锁版本字段
    @Version
    private Integer version;

    // 逻辑删除字段
    @TableLogic
    private Integer isDeleted;
}

3.3 Mapper 接口(核心 BaseMapper)

继承BaseMapper<T>,自动获得单表所有 CRUD 方法,无需写 XML

复制代码
package com.example.mp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mp.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
    // 内置方法:insert、deleteById、updateById、selectById、selectList等
}

3.4 Service 层(可选,封装业务)

MP 提供ServiceImpl实现类,封装批量操作、分页查询

复制代码
// Service接口
public interface UserService extends IService<User> {
}

// Service实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

四、内置通用 CRUD 操作(BaseMapper)

4.1 新增 insert

复制代码
@Autowired
private UserMapper userMapper;

@Test
void testInsert(){
    User user = new User();
    user.setUserName("张三");
    user.setAge(20);
    user.setEmail("zhangsan@163.com");
    // 返回受影响行数,自动回填自增id
    int rows = userMapper.insert(user);
    System.out.println("新增行数:"+rows);
    System.out.println("自增主键id:"+user.getId());
}

4.2 根据 id 查询 selectById

复制代码
User user = userMapper.selectById(1L);
System.out.println(user);

4.3 根据 id 更新 updateById

只更新实体中非 null 字段,不会覆盖原有数据

复制代码
User updateUser = new User();
updateUser.setId(1L);
updateUser.setAge(22);
userMapper.updateById(updateUser);

4.4 根据 id 删除 deleteById

复制代码
userMapper.deleteById(1L);

4.5 批量操作(IService 提供)

复制代码
@Autowired
private UserService userService;

// 批量新增
List<User> batchList = new ArrayList<>();
userService.saveBatch(batchList);
// 批量删除
userService.removeByIds(Arrays.asList(1L,2L,3L));

五、条件构造器 Wrapper

5.1 QueryWrapper 条件查询

复制代码
// 查询:年龄大于18,名字包含"张",按id降序
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18)
       .like("user_name", "张")
       .orderByDesc("id");
List<User> list = userMapper.selectList(wrapper);

5.2 LambdaQueryWrapper

复制代码
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.gt(User::getAge, 18)
             .like(User::getUserName, "张")
             .orderByDesc(User::getId);
List<User> list = userMapper.selectList(lambdaWrapper);

5.3 UpdateWrapper 条件更新

复制代码
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("age",20)
             .set("email", "update@qq.com");
userMapper.update(null, updateWrapper);

六、分页插件配置与分页查询

6.1 分页插件配置类

复制代码
package com.example.mp.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分页插件,指定数据库类型MySQL
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

6.2 分页查询代码

复制代码
// 参数1:当前页,参数2:每页条数
Page<User> page = new Page<>(1,5);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
// page接收分页结果,自动封装总条数、总页数、当前页数据
Page<User> resultPage = userMapper.selectPage(page, wrapper);

System.out.println("总记录数:"+resultPage.getTotal());
System.out.println("当前页数据:"+resultPage.getRecords());

七、高级功能

7.1 逻辑删除

配置文件已开启全局逻辑删除,调用deleteById不会真实删除数据,自动执行update set is_deleted=1,查询时自动过滤已删除数据。

复制代码
// 逻辑删除,底层执行update语句
userMapper.deleteById(1L);

7.2 乐观锁(解决并发更新丢失)

场景:多线程同时修改同一条数据,避免覆盖更新,通过 version 版本号实现。

  1. 实体添加@Version注解

  2. 配置类添加乐观锁插件

    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 分页插件
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    // 乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

  3. 更新逻辑:更新时校验 version,匹配成功 version+1,失败更新行数为 0

    User user = userMapper.selectById(1L);
    user.setAge(30);
    userMapper.updateById(user);

八、MyBatis-Plus 代码生成器

生成器依赖

xml

复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.3.1</version>
</dependency>
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
</dependency>

生成器测试类

复制代码
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import java.util.Collections;

public class CodeGenerator {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/test_db?serverTimezone=Asia/Shanghai", "root", "数据库密码")
                .globalConfig(builder -> {
                    builder.author("作者名") // 设置作者
                            .outputDir(System.getProperty("user.dir") + "/src/main/java"); // 输出路径
                })
                .packageConfig(builder -> {
                    builder.parent("com.example.mp") // 父包名
                            .moduleName("") // 模块名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
                })
                .strategyConfig(builder -> {
                    builder.addInclude("user") // 要生成的表名
                            .entityBuilder()
                            .enableLombok() // 开启lombok
                            .tableAnnotateEnable(true); // 开启表注解
                })
                .execute();
    }
}

九、总结

  1. 分页查询 total 为 0 :忘记配置PaginationInnerInterceptor分页插件;
  2. LambdaWrapper 报字段不存在 :实体字段和数据库映射错误,检查@TableField
  3. 逻辑删除不生效 :yml 未配置 logic-delete 相关参数,实体缺少@TableLogic
  4. 乐观锁更新失效:未添加乐观锁插件、更新时没有携带 version 字段;
  5. SQL 驼峰转换失效 :yml 关闭了map-underscore-to-camel-case
  6. Mapper 注入报错 :启动类缺少@MapperScan注解或包路径写错。

MyBatis-Plus 简化了 MyBatis 重复 CRUD 开发,核心使用流程:

  1. 引入 MP 依赖,配置数据库与 MP 参数;
  2. 实体类使用注解映射数据表;
  3. Mapper 继承 BaseMapper 获得通用 CRUD;
  4. LambdaWrapper 构造动态查询条件;
  5. 分页、逻辑删除、乐观锁按需开启插件;
  6. 代码生成器一键生成全套业务代码。

原生 MyBatis 复杂多表联查仍可以自定义 XML,MP 完全兼容,兼顾简单单表快速开发和复杂 SQL 自定义需求。

相关推荐
折哥的程序人生 · 物流技术专研8 小时前
Java面试通关⑩:MyBatis核心源码全集
mybatis·校招·java面试·orm框架·源码解析·数据库交互·社招
SeeYa-J1 天前
MyBatis(数据持久层,❗ “接口 = SQL执行器”)
mybatis
骑士雄师1 天前
java面试题:jvm ,mybatis
java·jvm·mybatis
风中芦苇啊1 天前
Java MyBatis 实战:如何通过 SQL 查询返回 List<Map> 数据格式
java·sql·mybatis
脑子运行超载2 天前
Jackson处理和mybatis的xml转换问题
xml·jackson·mybatis·javatype
杨运交2 天前
[042][数据模块]Mybatis Plus 数据库级租户:基于多数据源路由的动态隔离实现
数据库·oracle·mybatis
考虑考虑5 天前
Mybatis实现批量插入
java·后端·mybatis
敲个大西瓜18 天前
mybatis拦截器插件实现数据库字段加解密
mybatis