一、为什么选择 MyBatis-Plus?

MyBatis 虽然灵活,但需要手动编写大量 XML 映射文件或注解 SQL,而 MyBatis-Plus 解决了这些痛点:

无侵入:完全兼容 MyBatis,原有代码无需修改即可升级。

CRUD 自动生成:内置通用 Mapper/Service,单表操作无需写 SQL。

强大的条件构造器:支持链式调用,轻松构建复杂查询条件。

自动分页:无需手动处理分页参数,分页查询一键实现。

逻辑删除:无需修改 SQL,自动处理软删除逻辑。

代码生成器:一键生成 Entity、Mapper、Service、Controller 全套代码。

二、环境搭建(Spring Boot 整合)

1. 引入依赖

在 pom.xml 中添加 MyBatis-Plus 核心依赖(以 MySQL 为例):

<!-- Spring Boot 父工程 -->

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>2.7.10</version>

    <relativePath/>

</parent>



<!-- 核心依赖 -->

<dependencies>

    <!-- MyBatis-Plus 核心包 -->

    <dependency>

        <groupId>com.baomidou</groupId>

        <artifactId>mybatis-plus-boot-starter</artifactId>

        <version>3.5.3.1</version>

    </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>

    <!-- Spring Boot 测试 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-test</artifactId>

        <scope>test</scope>

    </dependency>

</dependencies>

2. 配置数据库连接

在 application.yml 中配置数据库和 MyBatis-Plus 基本信息:

spring:

  datasource:

    driver-class-name: com.mysql.cj.jdbc.Driver

    url: jdbc:mysql://localhost:3306/mp_demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai

    username: root

    password: 123456



# MyBatis-Plus 配置

mybatis-plus:

  # 实体类别名包扫描

  type-aliases-package: com.example.mpdemo.entity

  # 配置 mapper.xml 扫描路径(可选)

  mapper-locations: classpath:mapper/**/*.xml

  # 日志配置(方便调试)

  configuration:

    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

  # 全局配置

  global-config:

    db-config:

      # 主键自增策略

      id-type: auto

      # 逻辑删除字段名(可选)

      logic-delete-field: isDeleted

      # 逻辑删除-未删除值

      logic-not-delete-value: 0

      # 逻辑删除-已删除值

      logic-delete-value: 1

3. 启动类添加注解

在 Spring Boot 启动类上添加 @MapperScan,扫描 Mapper 接口包:

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;



@SpringBootApplication

// 扫描 Mapper 接口所在包

@MapperScan("com.example.mpdemo.mapper")

public class MpDemoApplication {

    public static void main(String[] args) {

        SpringApplication.run(MpDemoApplication.class, args);

    }

}

三、核心功能实战

1. 基础 CRUD 操作(无需写 SQL)

步骤 1:创建实体类

以 User 表为例,使用 Lombok 简化代码:

import com.baomidou.mybatisplus.annotation.*;

import lombok.Data;

import java.time.LocalDateTime;



@Data // Lombok 自动生成 getter/setter/toString 等

@TableName("user") // 指定数据库表名(若类名与表名一致可省略)

public class User {

    // 主键(对应全局配置的 auto 自增)

    @TableId(type = IdType.AUTO)

    private Long id;

    // 用户名(若字段名与属性名一致可省略 @TableField)

    private String username;

    // 密码

    private String password;

    // 年龄

    private Integer age;

    // 邮箱

    private String email;

    // 逻辑删除字段

    @TableLogic

    private Integer isDeleted;

    // 创建时间(自动填充)

    @TableField(fill = FieldFill.INSERT)

    private LocalDateTime createTime;

    // 更新时间(自动填充)

    @TableField(fill = FieldFill.INSERT_UPDATE)

    private LocalDateTime updateTime;

}

步骤 2:创建 Mapper 接口

继承 BaseMapper,自动获得 CRUD 方法:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import com.example.mpdemo.entity.User;

import org.apache.ibatis.annotations.Mapper;



@Mapper

public interface UserMapper extends BaseMapper<User> {

    // 无需写任何代码,BaseMapper 已包含所有单表 CRUD

}

步骤 3:测试 CRUD 操作

import com.example.mpdemo.entity.User;

import com.example.mpdemo.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

public class CrudTest {



    @Autowired

    private UserMapper userMapper;



    // 新增

    @Test

    public void testInsert() {

        User user = new User();

        user.setUsername("张三");

        user.setPassword("123456");

        user.setAge(20);

        user.setEmail("zhangsan@test.com");

        // 插入数据,返回受影响行数

        int rows = userMapper.insert(user);

        System.out.println("新增成功,受影响行数:" + rows + ",主键ID:" + user.getId());

    }



    // 查询单个

    @Test

    public void testSelectById() {

        User user = userMapper.selectById(1L);

        System.out.println(user);

    }



    // 查询所有

    @Test

    public void testSelectList() {

        List<User> userList = userMapper.selectList(null); // null 表示无查询条件

        userList.forEach(System.out::println);

    }



    // 更新

    @Test

    public void testUpdateById() {

        User user = new User();

        user.setId(1L);

        user.setAge(21); // 只更新年龄

        int rows = userMapper.updateById(user);

        System.out.println("更新成功,受影响行数:" + rows);

    }



    // 删除(物理删除)

    @Test

    public void testDeleteById() {

        int rows = userMapper.deleteById(1L);

        System.out.println("删除成功,受影响行数:" + rows);

    }



    // 逻辑删除(实际执行 update,将 isDeleted 设为 1)

    @Test

    public void testLogicDelete() {

        int rows = userMapper.deleteById(2L);

        System.out.println("逻辑删除成功,受影响行数:" + rows);

    }

}

2. 条件构造器(Wrapper):构建复杂查询

QueryWrapper/LambdaQueryWrapper 是 MP 最强大的功能之一,支持链式构建查询条件:

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.example.mpdemo.entity.User;

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

public class WrapperTest {



    @Autowired

    private UserMapper userMapper;



    // 基础 QueryWrapper(字符串字段名,易出错)

    @Test

    public void testQueryWrapper() {

        QueryWrapper<User> wrapper = new QueryWrapper<>();

        // 年龄大于 18 且用户名包含 "张" 且邮箱不为空

        wrapper.gt("age", 18)

               .like("username", "张")

               .isNotNull("email");

        List<User> userList = userMapper.selectList(wrapper);

        userList.forEach(System.out::println);

    }



    // LambdaQueryWrapper(类型安全,推荐)

    @Test

    public void testLambdaQueryWrapper() {

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        // 避免手写字段名,防止拼写错误

        wrapper.gt(User::getAge, 18)

               .like(User::getUsername, "张")

               .isNotNull(User::getEmail);

        List<User> userList = userMapper.selectList(wrapper);

        userList.forEach(System.out::println);

    }



    // 分页查询

    @Test

    public void testPage() {

        // 1. 构建分页条件:第 1 页,每页 10 条

        Page<User> page = new Page<>(1, 10);

        // 2. 构建查询条件

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();

        wrapper.gt(User::getAge, 18);

        // 3. 执行分页查询

        Page<User> resultPage = userMapper.selectPage(page, wrapper);

        // 4. 获取分页结果

        System.out.println("总记录数:" + resultPage.getTotal());

        System.out.println("总页数:" + resultPage.getPages());

        System.out.println("当前页数据:");

        resultPage.getRecords().forEach(System.out::println);

    }

}

3. 自动填充(创建 / 更新时间)

实现 MetaObjectHandler,自动填充创建时间和更新时间:

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;

import org.apache.ibatis.reflection.MetaObject;

import org.springframework.stereotype.Component;

import java.time.LocalDateTime;



@Component // 必须交给 Spring 管理

public class MyMetaObjectHandler implements MetaObjectHandler {



    // 插入时填充

    @Override

    public void insertFill(MetaObject metaObject) {

        // 填充 createTime 和 updateTime

        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());

        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());

    }



    // 更新时填充

    @Override

    public void updateFill(MetaObject metaObject) {

        // 只填充 updateTime

        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());

    }

}

4. 代码生成器(一键生成全套代码)

MP 提供代码生成器,可快速生成 Entity、Mapper、Service、Controller,减少重复工作。

引入代码生成器依赖:

<!-- MyBatis-Plus 代码生成器 -->

<dependency>

    <groupId>com.baomidou</groupId>

    <artifactId>mybatis-plus-generator</artifactId>

    <version>3.5.3.1</version>

</dependency>

<!-- 模板引擎(Freemarker) -->

<dependency>

    <groupId>org.freemarker</groupId>

    <artifactId>freemarker</artifactId>

    <version>2.3.31</version>

</dependency>

编写生成器代码:

import com.baomidou.mybatisplus.generator.FastAutoGenerator;

import com.baomidou.mybatisplus.generator.config.OutputFile;

import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Collections;



public class CodeGenerator {

    public static void main(String[] args) {

        // 数据库连接配置

        String url = "jdbc:mysql://localhost:3306/mp_demo?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";

        String username = "root";

        String password = "123456";



        // 快速生成代码

        FastAutoGenerator.create(url, username, password)

                // 全局配置

               .globalConfig(builder -> {

                    builder.author("你的名字") // 设置作者

                           .outputDir(System.getProperty("user.dir") + "/src/main/java") // 输出目录

                           .enableSwagger() // 开启 Swagger(可选)

                           .commentDate("yyyy-MM-dd") // 注释日期格式

                           .disableOpenDir(); // 生成后不打开文件夹

                })

                // 包配置

               .packageConfig(builder -> {

                    builder.parent("com.example.mpdemo") // 父包名

                           .moduleName("") // 模块名(无则空)

                           .entity("entity") // 实体类包名

                           .mapper("mapper") // Mapper 包名

                           .service("service") // Service 包名

                           .controller("controller") // Controller 包名

                           .pathInfo(Collections.singletonMap(OutputFile.mapperXml, System.getProperty("user.dir") + "/src/main/resources/mapper")); // Mapper XML 路径

                })

                // 策略配置

               .strategyConfig(builder -> {

                    builder.addInclude("user") // 要生成的表名(多个用逗号分隔)

                           .addTablePrefix("t_", "sys_") // 忽略表前缀(如 t_user → User)

                            // 实体类策略

                           .entityBuilder()

                           .enableLombok() // 启用 Lombok

                           .enableTableFieldAnnotation() // 生成字段注解

                            // Controller 策略

                           .controllerBuilder()

                           .enableRestStyle() // 生成 RestController

                           .enableHyphenStyle() // URL 中驼峰转连字符(如 userInfo → user-info)

                            // Service 策略

                           .serviceBuilder()

                           .formatServiceFileName("%sService") // Service 命名规则

                           .formatServiceImplFileName("%sServiceImpl");

                })

                // 模板引擎(Freemarker)

               .templateEngine(new FreemarkerTemplateEngine())

                // 执行生成

               .execute();

    }

}

四、进阶技巧

1. 自定义 SQL

若 MP 内置方法无法满足需求,可自定义 SQL(兼容 MyBatis 写法):


// UserMapper.java

@Select("SELECT * FROM user WHERE age > #{age}")

List<User> selectByAge(@Param("age") Integer age);



// 或在 UserMapper.xml 中编写

<select id="selectByAge" resultType="com.example.mpdemo.entity.User">

    SELECT * FROM user WHERE age > #{age}

</select>

2. 多表关联查询

MP 不直接支持多表关联,但可通过 @Select 注解或 XML 实现,结合 Wrapper 灵活拼接条件。

3. 乐观锁

解决并发更新问题,步骤:

实体类添加版本字段 @Version:

@Version

private Integer version;

配置乐观锁插件:


import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;

import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;

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 OptimisticLockerInnerInterceptor());

        // 添加分页插件

        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());

        return interceptor;

    }

}
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐