MyBatisPlus核心

3 阅读8分钟

MyBatis-Plus(简称 MP)是一个基于 MyBatis 的增强工具,在 MyBatis 的基础上实现了自动化 CRUD 操作,极大地简化了开发工作量。以下将从其核心功能、特性及使用场景等方面进行详细介绍:

一、核心功能与特性

1. 代码生成器(Code Generator)

  • 功能:自动生成 Entity、Mapper、Service、Controller 等基础代码,减少重复开发。
  • 优势:可通过配置数据库表结构,一键生成符合项目规范的代码,支持自定义模板(如注释格式、包路径等)。
  • 示例配置
@SpringBootApplication
public class MyBatisPlusApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBatisPlusApplication.class, args);
    }
    // 代码生成器配置(通常在配置类中)
    @Bean
    public CodeGenerator codeGenerator() {
        CodeGenerator generator = new CodeGenerator();
        generator.setDataSource(new DataSourceConfig()
            .setUrl("jdbc:mysql://localhost:3306/test")
            .setDriverName("com.mysql.cj.jdbc.Driver")
            .setUsername("name")//自己的
            .setPassword("pwd"));
        generator.setStrategy(new StrategyConfig()
            .setInclude("user", "order")); // 生成指定表的代码
        return generator;
    }
}
public class FastAutoGeneratorTest {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&useSSL=false", "name", "pwd")//自己的
                .globalConfig(builder -> {
                    builder.author("xxx") // 设置作者
                            //.enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir("D://mp"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.xxx") // 设置父包名,即公司名
                            .moduleName("mp") // 设置父包模块名
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mp")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude() // 设置需要生成的表名,不写参数代表数据库下的所有表,写参数如"user"代表user表
                            .addTablePrefix("tb_", "cb_") // 设置过滤表前缀
                            .controllerBuilder().enableRestStyle()
                            .serviceBuilder().formatServiceFileName("%sService").formatServiceImplFileName("%sServiceImpl");
                })
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}

扩展

代码对比分析
1. 版本差异
  • 第一段代码:使用的是MyBatis-Plus 3.4.3 及以下版本CodeGenerator(旧版 API)。
  • 第二段代码:使用的是MyBatis-Plus 3.5.0 及以上版本FastAutoGenerator(新版 API)。
2. 核心功能对比
功能点CodeGenerator(旧版)FastAutoGenerator(新版)
数据源配置需显式创建DataSourceConfig对象链式调用直接配置 URL、用户名、密码
表选择策略setInclude("user", "order")指定表名addInclude()支持可变参数或无参(生成所有表)
包路径配置无明确模块化配置packageConfig支持父包名、模块名、自定义路径映射
文件输出控制无明确覆盖选项fileOverride()支持覆盖已生成文件
模板引擎默认使用 Velocity默认使用 Velocity,可切换为 Freemarker(.templateEngine()
代码风格需手动配置内置enableRestStyle()生成 RestController 风格代码
命名策略无明确支持formatServiceFileName等方法自定义文件命名
3. 代码结构与易用性
  • 旧版(CodeGenerator)

    • 结构较分散,需创建多个配置对象(如DataSourceConfigStrategyConfig)。
    • 配置项较少,灵活性较低,但适合快速上手。
  • 新版(FastAutoGenerator)

    • 采用链式调用,代码更简洁流畅。
    • 功能更丰富,支持更多自定义选项(如 Swagger 注解、Rest 风格、自定义命名)。
    • 推荐使用,尤其是 MyBatis-Plus 3.5.x 及以上版本。
4. 示例差异点
  • 表选择

    • 旧版:setInclude("user", "order")
    • 新版:addInclude()(无参时生成所有表,或传入表名)
  • 输出路径

    • 旧版:未显式配置,默认输出到项目路径。
    • 新版:outputDir("D://mp")pathInfo()可精确控制各文件输出位置。
  • 命名策略

    • 旧版:使用默认命名(如UserServiceImpl)。
    • 新版:可通过formatServiceFileName("%sService")自定义。
5. 最佳实践建议
  1. 优先使用新版 APIFastAutoGenerator提供了更现代的 API 设计和更丰富的功能。

  2. 升级注意事项

    • 若项目已使用旧版CodeGenerator,升级后需迁移至FastAutoGenerator
    • 注意依赖版本兼容(MyBatis-Plus 3.5.x 需匹配对应版本的模板引擎)。

2. 通用 Mapper(BaseMapper)

  • 核心接口BaseMapper<T>提供通用 CRUD 方法,无需手动编写 SQL。

  • 支持方法

    • insert(T entity):插入单条记录
    • deleteById(Serializable id):根据 ID 删除
    • updateById(T entity):根据 ID 更新
    • selectById(Serializable id):根据 ID 查询
    • selectList(Wrapper<T> queryWrapper):条件查询列表
  • 示例

// UserMapper接口继承BaseMapper
public interface UserMapper extends BaseMapper<User> {
    // 自定义方法可在此扩展,无需实现通用CRUD
}

3. 条件构造器(Wrapper)

  • 作用:以面向对象的方式构建 SQL 查询条件,避免手写 SQL 字符串。

  • 核心类

    • QueryWrapper<T>:查询条件构造器
    • UpdateWrapper<T>:更新条件构造器
    • LambdaQueryWrapper<T>:Lambda 表达式风格构造器(推荐使用,避免字符串硬编码)
  • 示例

// 查询年龄>18且姓名包含"张"的用户,按年龄降序排列
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
    .gt(User::getAge, 18)
    .like(User::getName, "张")
    .orderByDesc(User::getAge);
List<User> userList = userMapper.selectList(wrapper);

4. 分页插件(Pagination)

  • 功能:支持物理分页,自动生成分页 SQL,兼容多种数据库(MySQL、Oracle 等)。

  • 使用方式

    • 配置分页插件(如MybatisPlusInterceptor
    • 调用selectPage(Page<T> page, Wrapper<T> queryWrapper)方法
  • 示例

// 配置分页插件(通常在MyBatis配置类中)
@Configuration
public class MyBatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

// 业务代码中使用分页
Page<User> page = new Page<>(1, 10); // 第1页,每页10条
userMapper.selectPage(page, null);
long total = page.getTotal(); // 总记录数
List<User> records = page.getRecords(); // 当前页数据

5. 自动填充(MetaObjectHandler)

  • 场景:自动填充创建时间、更新时间、创建人、更新人等公共字段。

  • 实现方式

    • 实现MetaObjectHandler接口
    • 在 Entity 中使用@TableField(fill = FieldFill.INSERT)等注解标记字段
  • 示例

// 实体类字段标记
public class User {
    private Long id;
    private String name;
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    // getter/setter省略
}

// 自动填充处理器
@Component
public class MetaObjectHandlerImpl implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        setFieldValByName("createTime", new Date(), metaObject);
        setFieldValByName("updateTime", new Date(), metaObject);
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        setFieldValByName("updateTime", new Date(), metaObject);
    }
}

6. 乐观锁(OptimisticLocker)

  • 作用:解决并发更新时的数据竞争问题,通过版本号(version)实现。

  • 使用步骤

    1. 表中添加version字段
    2. 实体类中使用@Version注解标记
    3. 配置乐观锁插件
  • 示例

// 实体类字段标记
public class User {
    private Long id;
    private String name;
    @Version
    private Integer version;
    // 其他字段省略
}

// 配置乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

二、核心扩展功能

1. 逻辑删除(LogicDelete)

  • 原理:通过标记字段(如deleted)实现数据软删除,查询时自动过滤已删除记录。

  • 使用方式

    • 表中添加deleted字段(类型通常为intboolean
    • 实体类中使用@TableLogic注解标记
    • 配置逻辑删除插件
  • 示例

// 实体类字段标记
public class User {
    private Long id;
    private String name;
    @TableLogic
    private Integer deleted; // 0未删除,1已删除
    // 其他字段省略
}

// 配置逻辑删除插件(全局配置中)
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new LogicSqlInjector());
        return interceptor;
    }
}

2. 主键生成策略(IdGenerator)

  • 支持策略

    • AUTO:数据库自增(如 MySQL 的AUTO_INCREMENT
    • INPUT:手动输入
    • ASSIGN_ID:MP 提供的雪花算法(默认,生成 19 位长整型 ID,全局唯一)
    • ASSIGN_UUID:生成 32 位 UUID
  • 示例

public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    // 其他字段省略
}

3. 自定义 SQL 注入器(SqlInjector)

  • 场景:扩展BaseMapper的通用方法,或自定义全局 SQL 逻辑。
  • 示例:添加自定义通用方法selectByStatus
public class CustomSqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new SelectByStatus()); // 添加自定义方法
        return methodList;
    }
}

// 自定义方法实现
public class SelectByStatus extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql = "SELECT * FROM " + tableInfo.getTableName() + " WHERE status = #{status}";
        SqlSource sqlSource = new RawSqlSource(configuration, sql, modelClass);
        return this.addSelectMappedStatementForOther(mapperClass, "selectByStatus", sqlSource, modelClass);
    }
}

三、核心架构与原理

1. 插件机制(Interceptor)

  • 核心类MybatisPlusInterceptor,通过责任链模式加载各类插件(分页、乐观锁、逻辑删除等)。
  • 原理:基于 MyBatis 的拦截器(Interceptor)机制,在 SQL 执行前对 SQL 进行改写或增强。

2. SQL 解析与生成

  • 核心组件

    • SqlBuilder:构建基础 SQL 片段(如SELECTWHERE
    • Wrapper:将条件转换为 SQL 参数
    • MetaObjectHandler:处理字段填充逻辑
  • 优势:避免手写 SQL,减少 SQL 注入风险,同时保持 MyBatis 的灵活性。

四、应用场景与优势

1. 适用场景

  • 中小型项目:快速开发,减少 CRUD 代码量。
  • 大型项目:统一数据访问层规范,便于团队协作。
  • 复杂查询场景:结合 MyBatis 原生 SQL,灵活扩展功能。

2. 核心优势

  • 效率提升:自动生成代码,通用 CRUD 无需手写 SQL。
  • 代码简洁:减少 XML 配置或注解,提升代码可读性。
  • 兼容性强:完全兼容 MyBatis,可无缝集成现有 MyBatis 项目。
  • 生态丰富:支持 Spring Boot、Spring Cloud 等主流框架,社区活跃。

五、快速入门示例

1. 添加依赖

<dependencies>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version> <!-- 最新版本可查询MP官网 -->
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.28</version>
    </dependency>
</dependencies>

2. 配置文件(application.yml)

  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8
    username: root
    password: 123456
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml  # Mapper.xml路径
  type-aliases-package: com.example.entity  # 实体类包路径
  configuration:
    map-underscore-to-camel-case: true  # 驼峰命名转换

3. 实体类与 Mapper

// 实体类
@Data
@TableName("user")
public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

// Mapper接口
public interface UserMapper extends BaseMapper<User> {
    // 可扩展自定义方法
}

4. 服务层与控制器

// Service接口(继承IService)
public interface UserService extends IService<User> {
    // 扩展业务方法
}

// Service实现类(继承ServiceImpl)
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    // 实现业务方法
}

// 控制器
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    
    @GetMapping("/list")
    public List<User> list() {
        return userService.list();
    }
    
    @PostMapping("/save")
    public boolean save(@RequestBody User user) {
        return userService.save(user);
    }
}

总结

MyBatis-Plus 通过自动化 CRUD条件构造器代码生成器等核心功能,大幅提升了开发效率,同时保持了 MyBatis 的灵活性。其核心设计思想是 “约定大于配置”,适合各类 Java 项目中简化数据访问层的开发。如果需要更复杂的 SQL 操作,仍可结合 MyBatis 原生 XML 或注解实现,真正做到 “零侵入性” 扩展。