告别重复编码:从原生MyBatis无缝迁移到MyBatis-Plus的实战指南

告别重复编码:从原生MyBatis无缝迁移到MyBatis-Plus的实战指南

【免费下载链接】mybatis-plus An powerful enhanced toolkit of MyBatis for simplify development 【免费下载链接】mybatis-plus 项目地址: https://gitcode.com/gh_mirrors/my/mybatis-plus

你是否还在手写大量重复的CRUD SQL?是否为分页查询的繁琐实现而头疼?本文将带你一步到位解决这些问题,通过实战案例展示如何将原生MyBatis项目平滑迁移到MyBatis-Plus,让开发效率提升300%。读完本文,你将掌握依赖替换、代码改造、高级功能应用的完整流程,并学会避迁移过程中的常见 pitfalls。

为什么选择MyBatis-Plus?

MyBatis-Plus(简称MP)是一个MyBatis的增强工具包,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。其核心优势包括:

  • 无侵入:引入MP不会对现有MyBatis架构产生任何影响
  • 通用CRUD操作:内置通用Mapper、通用Service,无需编写SQL即可完成单表操作
  • 强大的条件构造器:支持Lambda风格API,轻松构建复杂查询条件
  • 内置分页插件:物理分页无需手动编写limit语句
  • 多种主键策略:支持分布式唯一ID生成器,完美解决主键问题

MyBatis-Plus架构

官方文档:README.md

迁移准备:环境与依赖配置

1. 移除原生MyBatis依赖

在迁移前,首先需要从项目中移除原生MyBatis相关依赖,避免版本冲突。

2. 添加MyBatis-Plus依赖

根据你的Spring Boot版本选择合适的starter:

Spring Boot 2.x

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>Latest Version</version>
</dependency>

Spring Boot 3.x

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>Latest Version</version>
</dependency>

Spring Boot 4.x

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot4-starter</artifactId>
    <version>Latest Version</version>
</dependency>

依赖配置详情:README-zh.md

核心迁移步骤

1. 配置类改造

将原有的MyBatis配置类替换为MyBatis-Plus的配置类,主要变化是使用MybatisConfiguration替代MyBatis原生的Configuration

@Configuration
@MapperScan("com.example.mapper")
public class MyBatisPlusConfig {
    
    @Bean
    public MybatisConfiguration mybatisConfiguration() {
        return new MybatisConfiguration();
    }
}

MyBatis-Plus核心配置类:mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisConfiguration.java

2. Mapper接口改造

最关键的一步是让你的Mapper接口继承MP提供的BaseMapper,从而获得内置的CRUD方法:

原生MyBatis Mapper:

public interface UserMapper {
    User selectById(Long id);
    int insert(User user);
    int updateById(User user);
    int deleteById(Long id);
    List<User> selectList();
}

改造为MyBatis-Plus Mapper:

public interface UserMapper extends BaseMapper<User> {
    // 继承后无需编写基本CRUD方法
    // 保留自定义的复杂查询方法
}

BaseMapper接口提供的方法包括:

  • selectById(id):根据ID查询
  • selectList(queryWrapper):条件查询
  • insert(entity):插入
  • updateById(entity):根据ID更新
  • deleteById(id):根据ID删除
  • 以及更多批量操作方法...

Mapper接口处理逻辑:mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisMapperRegistry.java

3. 实体类注解改造

使用MP的注解替换XML配置或原生MyBatis注解,主要注解包括:

@Data
@TableName("t_user") // 指定表名
public class User {
    
    @TableId(type = IdType.AUTO) // 主键策略
    private Long id;
    
    @TableField("username") // 指定字段名
    private String name;
    
    private Integer age;
    
    @TableField(fill = FieldFill.INSERT) // 自动填充
    private LocalDateTime createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    
    @TableLogic // 逻辑删除
    private Integer deleted;
}

注解定义:mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/

4. Service层改造

Service层同样可以通过继承IService接口获得更强大的批量操作能力:

public interface UserService extends IService<User> {
}

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

通过ServiceImpl提供的方法,可以轻松实现:

// 批量插入
boolean saveBatch(Collection<User> entityList);

// 批量更新
boolean updateBatchById(Collection<User> entityList);

// 分页查询
IPage<User> page(IPage<User> page, QueryWrapper<User> queryWrapper);

查询方式优化

1. 条件构造器替代XML/SQL注解

原生MyBatis方式:

<select id="selectByCondition" resultType="User">
    SELECT * FROM t_user 
    WHERE age > #{age} 
    AND username LIKE CONCAT('%', #{name}, '%')
    ORDER BY create_time DESC
</select>

MyBatis-Plus条件构造器:

List<User> userList = userMapper.selectList(new QueryWrapper<User>()
    .gt("age", 18)
    .like("username", "张")
    .orderByDesc("create_time")
);

更安全的Lambda条件构造器:

List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>()
    .gt(User::getAge, 18)
    .like(User::getName, "张")
    .orderByDesc(User::getCreateTime)
);

条件构造器实现:mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/

2. 分页查询简化

原生MyBatis分页:

<select id="selectPage" resultType="User">
    SELECT * FROM t_user 
    LIMIT #{pageNum}, #{pageSize}
</select>

MyBatis-Plus分页:

// 配置分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
}

// 使用分页
IPage<User> page = new Page<>(1, 10);
IPage<User> userPage = userMapper.selectPage(page, new QueryWrapper<User>().gt("age", 18));
List<User> records = userPage.getRecords(); // 数据列表
long total = userPage.getTotal(); // 总条数
long pages = userPage.getPages(); // 总页数

分页插件实现:mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/plugins/PaginationInnerInterceptor.java

高级特性应用

1. 自动填充功能

实现元对象处理器接口,配置字段自动填充:

@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());
    }
}

元对象处理器接口:mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/MetaObjectHandler.java

2. 逻辑删除

通过@TableLogic注解实现逻辑删除,而非物理删除:

@TableLogic
private Integer deleted;

// 配置逻辑删除值
mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted
      logic-delete-value: 1
      logic-not-delete-value: 0

使用逻辑删除后,调用deleteById方法实际执行的是更新操作:

UPDATE t_user SET deleted=1 WHERE id=? AND deleted=0

逻辑删除注解:mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/TableLogic.java

3. 枚举处理器

使用MP的枚举处理器,简化枚举类型的数据库存储:

public enum GenderEnum implements IEnum<Integer> {
    MALE(1, "男"),
    FEMALE(0, "女");
    
    private final int value;
    private final String desc;
    
    GenderEnum(int value, String desc) {
        this.value = value;
        this.desc = desc;
    }
    
    @Override
    public Integer getValue() {
        return value;
    }
}

// 实体类中使用
@TableField("gender")
private GenderEnum gender;

枚举接口定义:mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/IEnum.java

迁移常见问题及解决方案

1. 方法名冲突

问题:自定义方法与BaseMapper中的方法名冲突
解决方案:重命名自定义方法或使用@SqlParser(filter = true)注解排除

2. 分页插件不生效

问题:分页查询返回全部数据而非分页结果
解决方案:确保正确配置了分页插件并使用MP提供的Page对象

3. 条件构造器字段名错误

问题:使用字符串形式的条件构造器时字段名拼写错误
解决方案:改用Lambda条件构造器,编译期检查字段名正确性

4. 枚举类型处理异常

问题:枚举类型无法正确转换
解决方案:确保枚举类实现IEnum接口或正确配置枚举处理器

迁移效果对比

功能原生MyBatisMyBatis-Plus代码量减少
单表CRUD需要编写XML/SQL继承BaseMapper即可90%
条件查询编写动态SQL条件构造器链式调用70%
分页查询手动编写LIMIT分页插件+Page对象80%
批量操作手动编写循环saveBatch/updateBatch85%

MyBatis-Plus效率提升

总结与展望

通过本文介绍的迁移步骤,你已经掌握了从原生MyBatis迁移到MyBatis-Plus的核心技巧。迁移后,你将获得:

  1. 大幅减少重复代码,专注业务逻辑
  2. 提高开发效率,缩短项目周期
  3. 增强代码可维护性和可读性
  4. 获得丰富的高级特性支持

MyBatis-Plus的生态还在不断发展,更多强大功能如代码生成器、多租户插件等等待你去探索。建议在迁移完成后,逐步深入学习这些高级特性,进一步提升开发效率。

代码生成器模块:mybatis-plus-generator/

提示:迁移过程建议分模块进行,先从非核心业务模块开始,验证无误后再迁移核心模块,确保系统稳定过渡。

MyBatis-Plus社区支持

【免费下载链接】mybatis-plus An powerful enhanced toolkit of MyBatis for simplify development 【免费下载链接】mybatis-plus 项目地址: https://gitcode.com/gh_mirrors/my/mybatis-plus

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值