高效开发秘籍:CRUD增强实战

作为常年奋战在业务代码一线的老码农,我深知传统 MyBatis 开发中那些烦人的重复劳动。每次新开一个模块,Controller、Service、Mapper、XML 四件套轮番上阵,尤其是那些基础的增删改查,代码写得手软。直到团队全面拥抱 MyBatis-Plus (简称 MP),才真正体会到了什么叫"解放生产力"。今天就跟大伙儿唠唠,MP 的 CRUD 增强到底强在哪,怎么用才最香。

一、传统 CRUD 的问题

想象一下这个场景:你要开发一个简单的用户管理模块。

  1. UserMapper.java 里定义接口:insert(User user), selectById(Long id), updateById(User user), deleteById(Long id)...
  2. UserMapper.xml 里吭哧吭哧写对应的 <insert>, <select>, <update>, <delete> SQL 语句。
  3. Service 层调用 Mapper,Controller 调用 Service... 一堆模板代码。
  • 重复劳动: 每个实体都要写一套几乎相同的 CRUD 操作。
  • 易错: SQL 手写,字段名容易拼错。
  • 维护难: 字段增减,所有相关 SQL 都得改。
  • 效率低: 大量时间花在基础操作上,而非核心业务。

二、MP:CRUD的增强

MP 的 CRUD 增强,核心在于帮我们进行一些自动化的基础操作,让我们将精力主要集中在逻辑层。主要体现在四个方面吧!

1:BaseMapper - 开箱即用的 CRUD 接口

核心思想: MP 为你的 Mapper 接口提供了一个功能强大的"爹" - BaseMapper<T>。你的 Mapper 只需要继承它,就自动拥有了数十个常用方法。

java 复制代码
// 1. 定义实体 (User.java)
@Data // Lombok 简化 getter/setter
@TableName("sys_user") // 指定表名(如果表名 != 类名)
public class User {
    @TableId(type = IdType.AUTO) // 主键策略:数据库自增
    private Long id;
    private String username;
    private String password;
    private String email;
    private Integer status;
}

// 2. 你的 Mapper 接口,只需继承 BaseMapper,指定泛型为你的实体
@Mapper
public interface UserMapper extends BaseMapper<User> {
    // 无需再写 insert, selectById, updateById, deleteById 等方法声明!
    // BaseMapper 已经提供了它们!
}

// 3. 在 Service 或测试中直接使用注入的 userMapper
@Autowired
private UserMapper userMapper;

// 插入一条用户 (自动处理主键、字段映射)
User newUser = new User(null, "zhangsan", "encrypted_pwd", "zs@example.com", 1);
int insertCount = userMapper.insert(newUser); // 返回影响行数
System.out.println("插入成功,ID为: " + newUser.getId()); // 自增ID回填

// 根据ID查询
User user = userMapper.selectById(1L);

// 根据ID更新 (注意:更新哪个字段,取决于你的 user 对象哪些属性不为null)
User updateUser = new User();
updateUser.setId(1L);
updateUser.setEmail("new_email@example.com");
int updateCount = userMapper.updateById(updateUser);

// 根据ID删除
int deleteCount = userMapper.deleteById(1L);

上述中有一个Lombok 简化 getter/setter,如果不知道Lombok的请看我这篇的介绍

BaseMapper类内部已经都封装好了比如添加,删除,查询,更新这些方面,直接调用就行。

优势: 省去所有基础 CRUD 的接口声明和 XML 编写!字段映射、SQL 生成 MP 全包了。

秘籍 2:IService / ServiceImpl - 服务层增强

核心思想: 服务层接口继承 IService<T>,实现类继承 ServiceImpl<M extends BaseMapper<T>, T> implements IService<T>,获得更强的业务封装能力。

优势: 服务层也无需写基础 CRUD 实现,代码更简洁,业务逻辑更集中。 有很多方法可以直接使用

秘籍 3:条件构造器 - 复杂查询的利器

核心思想: 告别手写 WHERE 条件!使用 QueryWrapper 或更类型安全的 LambdaQueryWrapper 来动态构建查询、更新、删除条件。这是 MP 的灵魂之一。

java 复制代码
// 场景1:查询状态为1、用户名包含"admin"、邮箱不为空的用户列表 (使用 LambdaQueryWrapper,类型安全,推荐!)
LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
lambdaQuery.eq(User::getStatus, 1)
           .like(User::getUsername, "admin")
           .isNotNull(User::getEmail)
           .orderByDesc(User::getId);
List<User> userList = userMapper.selectList(lambdaQuery); // 或 userService.list(lambdaQuery)

// 生成的 SQL 类似:SELECT ... FROM sys_user WHERE status = 1 AND username LIKE '%admin%' AND email IS NOT NULL ORDER BY id DESC

// 场景2:更新所有状态为0的用户,将其密码重置为'default_pwd'
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(User::getPassword, "default_pwd")
             .eq(User::getStatus, 0);
int updateCount = userMapper.update(null, updateWrapper); // 第一个参数为 null 表示不更新实体字段,只按 Wrapper 更新

// 生成的 SQL 类似:UPDATE sys_user SET password = 'default_pwd' WHERE status = 0

// 场景3:删除邮箱以 'test_' 开头的测试用户
LambdaQueryWrapper<User> deleteWrapper = new LambdaQueryWrapper<>();
deleteWrapper.likeRight(User::getEmail, "test_"); // 'test_%'
int deleteCount = userMapper.delete(deleteWrapper);

优势: 用 Java 代码优雅地构建复杂 SQL 条件,避免 SQL 注入,代码可读性强,易于维护。LambdaQueryWrapper 利用方法引用,编译时就能检查字段名正确性,极大减少拼写错误。

秘籍 4:分页插件 - 分页如此简单

核心思想: 配置一个分页拦截器 (PaginationInnerInterceptor),就能让你的查询方法轻松支持物理分页。

java 复制代码
// 1. 配置分页插件 (通常在 MyBatisPlusConfig 配置类中)
@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 根据数据库类型选择
        return interceptor;
    }
}

// 2. 在 Mapper 或 Service 中使用 Page 对象进行分页查询
// Service 层方式 (推荐)
Page<User> pageParam = new Page<>(1, 10); // 查询第1页,每页10条
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getStatus, 1);
Page<User> userPage = userService.page(pageParam, queryWrapper); // 核心分页方法

System.out.println("总记录数: " + userPage.getTotal());
System.out.println("总页数: " + userPage.getPages());
System.out.println("当前页数据: " + userPage.getRecords());

// Mapper 方式
Page<User> pageParam = new Page<>(1, 10);
LambdaQueryWrapper<User> queryWrapper = ...;
Page<User> userPage = userMapper.selectPage(pageParam, queryWrapper);

优势: 一行配置 + 一个 Page 参数,复杂的分页查询瞬间搞定,返回结果包含分页所有信息。

三、总结:高效秘籍的精髓

MyBatis-Plus 的 CRUD 增强秘籍,其核心精髓在于 "约定优于配置""强大的自动化"

  1. BaseMapper: 基础 CRUD 的自动化,告别重复声明和手写 SQL。
  2. IService/ServiceImpl: 服务层通用逻辑的封装,提升业务代码纯度。
  3. Wrapper (Lambda): 用类型安全的 Java 代码动态构建复杂 SQL 条件,安全高效。
  4. 分页插件: 极简配置实现标准分页功能。

四、如何使用?

要使用的话,千万还得记得在pom.xml文件中进行包的配置,不然的话写出来是会报错的

以SpringBoot为例,配置参数如下:

xml 复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus.version}</version>
</dependency>
相关推荐
CodeUp.12 分钟前
基于SpringBoot的OA办公系统的设计与实现
spring boot·后端·mybatis
小醉你真好17 分钟前
Spring Boot + ShardingSphere 分库分表实战
java·spring boot·后端·mysql
Jacob02341 小时前
Node.js 性能瓶颈与 Rust + WebAssembly 实战探索
后端·rust·node.js
王中阳Go1 小时前
分库分表之后如何使用?面试可以参考这些话术
后端·面试
知其然亦知其所以然1 小时前
ChatGPT太贵?教你用Spring AI在本地白嫖聊天模型!
后端·spring·ai编程
kinlon.liu2 小时前
内网穿透 FRP 配置指南
后端·frp·内网穿透
kfyty7252 小时前
loveqq-mvc 再进化,又一款分布式网关框架可用
java·后端
Dcr_stephen2 小时前
Spring 事务中的 beforeCommit 是业务救星还是地雷?
后端
raoxiaoya2 小时前
Golang中的`io.Copy()`使用场景
开发语言·后端·golang