MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,旨在简化开发、提高效率。它在 MyBatis 的基础上只做增强不做改变,为简化 CRUD 操作提供了强大支持,尤其在生成 Mapper 接口方面表现突出。


一、核心概念

1.1 Mapper 接口

  • 定义:Mapper 接口是 MyBatis/MyBatis-Plus 中用于定义数据库操作方法的 Java 接口。
  • 作用:通过接口方法与 SQL 映射,实现对数据库的增删改查(CRUD)。
  • MyBatis-Plus 特性:无需编写 SQL,继承 BaseMapper<T> 即可获得通用 CRUD 方法。

1.2 BaseMapper

  • 是 MyBatis-Plus 提供的通用 Mapper 接口,封装了常见的 CRUD 操作。
  • 示例:
    public interface UserMapper extends BaseMapper<User> {
        // 继承后自动拥有 insert, selectById, updateById, deleteById 等方法
    }
    

1.3 实体类(Entity)

  • 与数据库表对应的 Java 类,通常使用 Lombok 简化 Getter/Setter。
  • 需要使用 @TableName@TableId@TableField 等注解进行映射。

1.4 代码生成器(AutoGenerator)

  • MyBatis-Plus 提供的 AutoGenerator 工具可自动生成 Entity、Mapper、Service、Controller 等代码。
  • 支持自定义模板、包路径、数据库配置等。

二、操作步骤(详细)

以下步骤基于 Spring Boot + MyBatis-Plus 实现 Mapper 接口生成。

步骤 1:添加依赖(Maven)

<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- MyBatis-Plus Starter -->
    <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>

    <!-- 代码生成器依赖 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.5.3</version>
    </dependency>
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
    </dependency>
</dependencies>

⚠️ 注意:版本需兼容,建议使用最新稳定版。


步骤 2:配置数据库连接(application.yml)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # 控制台输出 SQL
  mapper-locations: classpath*:mapper/*.xml

步骤 3:创建实体类(Entity)

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

@Data
@TableName("user") // 指定表名
public class User {
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @TableField("name")
    private String name;

    @TableField("email")
    private String email;

    @TableField("status")
    private Integer status;
}

@TableId:主键注解,type = IdType.AUTO 表示数据库自增。


步骤 4:生成 Mapper 接口

方式一:手动创建

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
    // 可以添加自定义方法,如复杂查询
}

@Mapper 注解使 Spring 能扫描到该接口。也可在启动类加 @MapperScan("com.example.mapper")

方式二:使用代码生成器(推荐)

创建代码生成器类:

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.sql.Types;
import java.util.Collections;

public class CodeGenerator {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/test_db", "root", "your_password")
            .globalConfig(builder -> {
                builder.author("your_name") // 设置作者
                       .outputDir(System.getProperty("user.dir") + "/src/main/java"); // 输出路径
            })
            .dataSourceConfig(builder -> builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                if (typeCode == Types.SMALLINT) {
                    return DbColumnType.INTEGER;
                }
                return typeRegistry.getColumnType(metaInfo);
            }))
            .packageConfig(builder -> {
                builder.parent("com.example") // 设置父包名
                       .moduleName("demo")     // 模块名
                       .pathInfo(Collections.singletonMap(OutputFile.mapper, System.getProperty("user.dir") + "/src/main/java/com/example/mapper"));
            })
            .strategyConfig(builder -> {
                builder.entityBuilder()
                       .naming(NamingStrategy.underline_to_camel) // 下划线转驼峰
                       .columnNaming(NamingStrategy.underline_to_camel)
                       .enableLombok() // 启用 Lombok
                       .logicDeleteColumnName("deleted"); // 逻辑删除字段

                builder.mapperBuilder()
                       .enableFileOverride() // 覆盖已有文件(谨慎使用)
                       .enableBaseResultMap() // 生成 ResultMap
                       .enableBaseColumnList(); // 生成 BaseColumnList

                builder.serviceBuilder()
                       .enableFileOverride();

                builder.controllerBuilder()
                       .enableFileOverride();

                builder.addInclude("user"); // 指定要生成的表
            })
            .templateEngine(new FreemarkerTemplateEngine()) // 使用 Freemarker 模板引擎
            .execute();
    }
}

运行该类,自动生成:

  • User.java(Entity)
  • UserMapper.java(Mapper 接口)
  • UserService.java, UserController.java 等(可选)

步骤 5:注册 Mapper 扫描

在 Spring Boot 启动类上添加:

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

步骤 6:使用 Mapper 接口

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public void test() {
        User user = new User();
        user.setName("张三");
        user.setEmail("zhangsan@example.com");

        // 插入
        userMapper.insert(user);

        // 查询
        User dbUser = userMapper.selectById(1L);

        // 更新
        user.setEmail("new@example.com");
        userMapper.updateById(user);

        // 删除
        userMapper.deleteById(1L);
    }
}

三、常见错误与解决方案

错误 原因 解决方案
Invalid bound statement (not found) Mapper 接口未被扫描 检查 @MapperScan 路径或 @Mapper 注解
Unknown column 'xxx' in 'field list' 实体字段与数据库列名不匹配 使用 @TableField("column_name") 映射
主键未自增 @TableId 类型设置错误 设置 type = IdType.AUTO
生成器无法连接数据库 驱动或 URL 错误 检查 JDBC URL、用户名、密码
生成代码乱码 文件编码问题 设置 IDE 和项目编码为 UTF-8

四、注意事项

  1. 包扫描路径必须正确:确保 @MapperScan 包含所有 Mapper 接口。
  2. 数据库字段命名规范:建议使用下划线命名(如 user_name),Java 使用驼峰(userName),MP 会自动转换。
  3. 避免循环依赖:Service 中注入 Mapper,不要在 Mapper 中注入 Service。
  4. 逻辑删除字段需配置:在 application.yml 中配置:
    mybatis-plus:
      global-config:
        db-config:
          logic-delete-field: deleted
          logic-delete-value: 1
          logic-not-delete-value: 0
    
  5. 生成器慎用 enableFileOverride():会覆盖已有文件,建议开发初期使用。

五、使用技巧

  1. 批量操作

    userMapper.insertBatchSomeColumn(list); // 批量插入
    userMapper.deleteBatchIds(Arrays.asList(1L, 2L)); // 批量删除
    
  2. 条件构造器(Wrapper)

    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("status", 1).like("name", "王");
    List<User> users = userMapper.selectList(wrapper);
    
  3. 自定义 SQL: 在 Mapper 接口中添加方法并配合 XML 使用:

    @Select("SELECT * FROM user WHERE name LIKE #{name}")
    List<User> findByName(@Param("name") String name);
    

六、最佳实践与性能优化

6.1 最佳实践

  • 统一异常处理:结合 @RestControllerAdvice 处理数据库异常。

  • 使用分页插件

    @Configuration
    public class MyBatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
    }
    

    使用:

    Page<User> page = new Page<>(1, 10);
    userMapper.selectPage(page, null);
    
  • 逻辑删除代替物理删除:避免数据丢失。

6.2 性能优化

  • 避免 N+1 查询:使用 @Select + JOIN 查询关联数据。
  • 合理使用缓存:结合 Redis 缓存热点数据。
  • SQL 审计:开启 mybatis-plus.configuration.log-impl 查看执行 SQL。
  • 索引优化:在频繁查询的字段上建立索引。

七、总结

MyBatis-Plus 极大简化了 Mapper 接口的开发:

  • 继承 BaseMapper → 获得通用 CRUD
  • 使用代码生成器 → 快速生成全套代码
  • 结合 Wrapper → 实现复杂查询
  • 配合分页、逻辑删除 → 提升开发效率