完整教程:MyBatis-Plus使用详解

一、什么是 MyBatis-Plus?

MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

核心特性:

  1. 无侵入:只做增强不做改变,引入它不会对现有工程产生影响。

  2. 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作。

  3. 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求。

  4. 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错。

  5. 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题。

  6. 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。

  7. 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件后,写分页等同于普通 List 查询。

  8. 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询。

  9. 内置全局拦截插件:提供全表 deleteupdate 操作智能分析阻断,也可自定义拦截规则,预防误操作。

  10. 支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库。

二、快速入门

1. 添加依赖

以 Spring Boot 项目为例,在 pom.xml 中添加:


    
    
        org.springframework.boot
        spring-boot-starter
    
    
        org.springframework.boot
        spring-boot-starter-test
        test
    
    
    
        com.baomidou
        mybatis-plus-boot-starter
        3.5.6 
    
    
    
        mysql
        mysql-connector-java
        8.0.33
    
    
    
        org.projectlombok
        lombok
        true
    
2. 配置

在 application.yml 中配置数据源和 MyBatis-Plus:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus_demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
    username: root
    password: 123456
# MyBatis-Plus 配置
mybatis-plus:
  configuration:
    # 在控制台打印SQL日志,便于调试
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      # 全局逻辑删除的实体字段名 (since 3.3.0)
      logic-delete-field: deleted
      # 逻辑已删除值(默认为 1)
      logic-delete-value: 1
      # 逻辑未删除值(默认为 0)
      logic-not-delete-value: 0
      # 主键类型。AUTO-数据库ID自增,INPUT-自行设置,ASSIGN_ID-雪花算法,ASSIGN_UUID-UUID
      id-type: ASSIGN_ID
3. 创建实体类

使用 Lombok 注解简化代码。

import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("sys_user") // 指定表名,如果表名和类名一致(忽略大小写和下划线)可省略
public class User {
    /**
     * 主键
     */
    @TableId(type = IdType.ASSIGN_ID) // 使用雪花算法生成ID
    private Long id;
    /**
     * 用户名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 邮箱
     */
    private String email;
    /**
     * 创建时间
     */
    @TableField(fill = FieldFill.INSERT) // 插入时自动填充
    private LocalDateTime createTime;
    /**
     * 更新时间
     */
    @TableField(fill = FieldFill.INSERT_UPDATE) // 插入和更新时自动填充
    private LocalDateTime updateTime;
    /**
     * 逻辑删除字段 (0-未删除, 1-已删除)
     */
    @TableLogic
    private Integer deleted;
}

注解说明:

  • @TableName:表名注解。

  • @TableId:主键注解。IdType 常用值:

    • AUTO:数据库 ID 自增。

    • ASSIGN_ID:雪花算法生成 Long 类型的 ID(默认策略)。

    • ASSIGN_UUID:生成 UUID。

  • @TableField:字段注解。

    • fill:字段自动填充策略。FieldFill.INSERT(插入时填充),FieldFill.UPDATE(更新时填充),FieldFill.INSERT_UPDATE(插入和更新时都填充)。

    • value:数据库字段名(如果属性名和字段名符合驼峰命名规则,可省略)。

  • @TableLogic:逻辑删除注解。

4. 创建 Mapper 接口

继承 MyBatis-Plus 提供的 BaseMapper 接口。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
// 指定对应的实体类
public interface UserMapper extends BaseMapper {
    // 此时,已经拥有了 BaseMapper 中所有的基本 CRUD 方法
    // 无需编写 XML 文件
}

别忘了在启动类上添加 @MapperScan 注解:

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.demo.mapper") // 扫描 Mapper 接口所在的包
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
5. 测试

编写一个测试类,注入 UserMapper 进行测试。

import com.example.demo.entity.User;
import com.example.demo.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;
@SpringBootTest
class DemoApplicationTests {
    @Autowired
    private UserMapper userMapper;
    @Test
    void testSelect() {
        System.out.println("----- 查询所有用户 ------");
        List userList = userMapper.selectList(null);
        userList.forEach(System.out::println);
    }
    @Test
    void testInsert() {
        User user = new User();
        user.setName("张三");
        user.setAge(25);
        user.setEmail("zhangsan@example.com");
        int result = userMapper.insert(user);
        System.out.println("插入影响行数: " + result);
        System.out.println("生成的主键ID: " + user.getId());
    }
    @Test
    void testUpdate() {
        User user = new User();
        user.setId(1L);
        user.setAge(26);
        int result = userMapper.updateById(user);
        System.out.println("更新影响行数: " + result);
    }
    @Test
    void testDelete() {
        int result = userMapper.deleteById(1L);
        System.out.println("删除影响行数: " + result);
    }
}

三、核心功能详解

1. 条件构造器 Wrapper

Wrapper 是 MyBatis-Plus 最核心的功能之一,用于构建复杂的 SQL WHERE 条件。推荐使用 LambdaQueryWrapper,避免硬编码字段名。

@Test
void testQueryWrapper() {
    // 1. 查询年龄大于20且邮箱不为空的用户
    LambdaQueryWrapper wrapper1 = new LambdaQueryWrapper<>();
    wrapper1.gt(User::getAge, 20)
            .isNotNull(User::getEmail);
    List userList1 = userMapper.selectList(wrapper1);
    // 2. 查询名字包含"张"且年龄小于30的用户
    LambdaQueryWrapper wrapper2 = new LambdaQueryWrapper<>();
    wrapper2.like(User::getName, "张")
            .lt(User::getAge, 30);
    List userList2 = userMapper.selectList(wrapper2);
    // 3. 按年龄降序排序
    LambdaQueryWrapper wrapper3 = new LambdaQueryWrapper<>();
    wrapper3.orderByDesc(User::getAge);
    List userList3 = userMapper.selectList(wrapper3);
    // 4. 只查询指定的字段 (SELECT id, name FROM user ...)
    LambdaQueryWrapper wrapper4 = new LambdaQueryWrapper<>();
    wrapper4.select(User::getId, User::getName);
    List userList4 = userMapper.selectList(wrapper4);
}
2. 自定义 SQL

对于复杂的多表关联查询,仍然需要编写 XML 或注解形式的 SQL。

Mapper 接口:

public interface UserMapper extends BaseMapper {
    // 使用注解方式
    @Select("SELECT u.*, d.department_name FROM sys_user u LEFT JOIN sys_department d ON u.dept_id = d.id WHERE u.id = #{id}")
    User selectUserWithDepartment(Long id);
    // 使用 XML 方式 (推荐复杂SQL)
    User selectComplexUser(@Param("ew") Wrapper wrapper);
}

XML 文件 (UserMapper.xml):




    
3. 分页查询

首先需要配置分页插件。

配置类:

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();
        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

使用分页:

@Test
void testPage() {
    // 参数:当前页,每页大小
    Page page = new Page<>(1, 5);
    LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
    wrapper.gt(User::getAge, 20);
    // 执行查询
    Page userPage = userMapper.selectPage(page, wrapper);
    System.out.println("总记录数: " + userPage.getTotal());
    System.out.println("总页数: " + userPage.getPages());
    System.out.println("当前页数据: ");
    userPage.getRecords().forEach(System.out::println);
}
4. 通用 Service

MyBatis-Plus 提供了通用的 IService 接口及其实现类 ServiceImpl,进一步封装了常用服务层操作。

1. 创建 Service 接口:

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.entity.User;
public interface UserService extends IService {
    // 可以在这里定义自定义方法
    User getCustomUserById(Long id);
}

2. 创建 Service 实现类:

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {
    @Override
    public User getCustomUserById(Long id) {
        // 这里可以写复杂的业务逻辑
        return this.getById(id);
    }
}

3. 使用 Service:

@Autowired
private UserService userService;
@Test
void testService() {
    // 保存
    User user = new User();
    user.setName("李四");
    userService.save(user);
    // 批量查询
    List list = userService.list();
    // 链式查询
    List users = userService.lambdaQuery()
                                .gt(User::getAge, 20)
                                .like(User::getName, "张")
                                .list();
}
5. 自动填充(如创建时间、更新时间)

实现 MetaObjectHandler 接口。

1. 创建填充处理器:

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        // 插入时自动填充
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        // 更新时自动填充
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }
}

2. 在实体类字段上添加 @TableField 注解(见上文实体类示例)。

6. 逻辑删除

配置好全局逻辑删除(见上文 application.yml 配置)和在实体类字段上添加 @TableLogic 注解后,所有删除操作将自动变为更新操作,将 deleted 字段设置为 1。查询操作会自动带上 deleted = 0 的条件。

userMapper.deleteById(1L); // 实际执行的是 UPDATE user SET deleted=1 WHERE id=1 AND deleted=0
userMapper.selectList(null); // 实际执行的是 SELECT ... FROM user WHERE deleted=0

四、常用配置

一个更完整的 application.yml 配置示例:

mybatis-plus:
  # 配置 XML 文件位置
  mapper-locations: classpath*:/mapper/**/*.xml
  # 配置类型别名包
  type-aliases-package: com.example.demo.entity
  configuration:
    # 开启驼峰命名自动映射
    map-underscore-to-camel-case: true
    # 日志实现
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 配置JdbcTypeForNull,解决 updateById(id, null) 时,字段不更新问题
    jdbc-type-for-null: 'null'
  global-config:
    db-config:
      # 主键类型
      id-type: ASSIGN_ID
      # 逻辑删除字段名
      logic-delete-field: deleted
      # 逻辑已删除值
      logic-delete-value: 1
      # 逻辑未删除值
      logic-not-delete-value: 0
      # 表名前缀(如果所有表都有共同前缀,可以在此配置)
      # table-prefix: t_

五、总结

MyBatis-Plus 通过以下方式极大地提升了开发效率:

  1. 开箱即用:继承 BaseMapper / IService 即可获得绝大部分单表 CRUD 方法。

  2. 条件构造器:使用 LambdaQueryWrapper 以 Lambda 形式安全、优雅地构建复杂查询条件。

  3. 代码生成器(本文未展开):可以快速生成 Entity、Mapper、Service、Controller 等全套代码。

  4. 内置插件:分页、性能分析、乐观锁、逻辑删除等常用功能都已内置。

  5. 无侵入性:与原生 MyBatis 完美共存,原有代码不受任何影响。

对于大多数业务场景,使用 MyBatis-Plus 可以让你告别简单的 CRUD 编写工作,更专注于核心业务逻辑的实现。

posted @ 2025-11-30 22:08  gccbuaa  阅读(0)  评论(0)    收藏  举报