5分钟上手!MyBatis-Plus 让你开发效率翻倍!

什么是 MyBatis-Plus?

简单来说,MyBatis-Plus是MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,既能够简化开发,又能够提高效率

我们就从最简单的开始吧!只需要几行代码就能搞定常见的 CRUD 操作。

如果你是新手,可以能快速的学习MyBatis-Plus,如果你是有经验的开发,也可以巩固一下相关的内容。

1. 添加依赖

xml

<!-- 在 pom.xml 中添加以下依赖 --> <dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.7.0</version> </dependency> <!-- MyBatis-Plus Starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency> <!-- 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!-- Lombok 简化实体类开发 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> <optional>true</optional> </dependency> </dependencies>

2. 配置数据源

yaml

# application.yml spring: datasource: # 替换成你的数据库信息 url: jdbc:mysql://localhost:3306/mybatis_plus_demo?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8 username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver # MyBatis-Plus 配置 mybatis-plus: configuration: # 打印 SQL 日志,方便调试 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true # 开启驼峰命名自动转换 global-config: db-config: # 逻辑删除配置 logic-delete-field: deleted # 全局逻辑删除的实体字段名 logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) id-type: auto # 主键ID自增

3. 实体类设计

java

import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.time.LocalDateTime; @Data @TableName("user") // 指定对应的数据库表名 public class User { /** * 用户ID - 主键 * @TableId 注解表示这是主键 * value = "id" 表示对应数据库字段名 * type = IdType.AUTO 表示主键自增 */ @TableId(value = "id", type = IdType.AUTO) private Long id; /** * 用户名 * 如果字段名与数据库列名一致(驼峰转下划线),可以省略 @TableField */ private String username; /** * 年龄 */ private Integer age; /** * 邮箱 */ private String email; /** * 创建时间 * @TableField 配置填充策略 */ @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; /** * 更新时间 * 插入和更新时都自动填充 */ @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; /** * 逻辑删除字段 * 0-未删除 1-已删除 */ @TableLogic private Integer deleted; }

4. Mapper 接口

java

import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; /** * UserMapper 接口 * 继承 BaseMapper 就自动拥有了 CRUD 方法 * * 注意:BaseMapper<User> 中的 User 是实体类类型 */ @Mapper // 一定要加上 @Mapper 注解,Spring 才能扫描到 public interface UserMapper extends BaseMapper<User> { // 不需要写任何方法,基本的 CRUD 都已经有了! /** * 如果需要自定义SQL,可以这样写 */ // @Select("SELECT * FROM user WHERE age > #{minAge}") // List<User> selectUsersByMinAge(@Param("minAge") Integer minAge); }

5. 服务层实现

java

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** * UserService 实现类 * * 继承 ServiceImpl 就自动拥有了更多的 CRUD 方法 * 参数说明: * - UserMapper:你的 Mapper 接口 * - User:你的实体类 */ @Service public class UserService extends ServiceImpl<UserMapper, User> { // 可以在这里添加自定义的业务方法 /** * 自定义方法:根据用户名查询用户 */ public User getUserByUsername(String username) { // 使用 MP 的查询构造器 return lambdaQuery() .eq(User::getUsername, username) // username = ? .one(); // 查询一条记录 } /** * 自定义方法:根据邮箱后缀查询用户 */ public List<User> getUsersByEmailSuffix(String emailSuffix) { return lambdaQuery() .likeRight(User::getEmail, emailSuffix) // email like 'emailSuffix%' .list(); } }

6. 新增操作

java

@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; /** * 新增用户 */ @PostMapping public String addUser(@RequestBody User user) { // 方法1:使用 save 方法 boolean success = userService.save(user); if (success) { return "新增用户成功,用户ID:" + user.getId(); } else { return "新增用户失败"; } } /** * 批量新增用户 */ @PostMapping("/batch") public String addUsers(@RequestBody List<User> users) { // 批量插入,每次插入100条 boolean success = userService.saveBatch(users, 100); return success ? "批量新增成功" : "批量新增失败"; } /** * 新增或更新用户(存在则更新,不存在则新增) */ @PostMapping("/save-or-update") public String saveOrUpdateUser(@RequestBody User user) { boolean success = userService.saveOrUpdate(user); return success ? "操作成功" : "操作失败"; } }

7. 查询操作

java

/** * 查询相关操作 */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; /** * 根据ID查询用户 */ @GetMapping("/{id}") public User getUserById(@PathVariable Long id) { return userService.getById(id); } /** * 查询所有用户 */ @GetMapping public List<User> getAllUsers() { return userService.list(); } /** * 条件查询:查询年龄大于18的用户 */ @GetMapping("/adults") public List<User> getAdultUsers() { return userService.lambdaQuery() .gt(User::getAge, 18) // age > 18 .list(); } /** * 复杂条件查询:年龄在18-60之间,并且用户名包含"张" */ @GetMapping("/complex") public List<User> getComplexUsers() { return userService.lambdaQuery() .between(User::getAge, 18, 60) // age between 18 and 60 .like(User::getUsername, "张") // username like '%张%' .orderByDesc(User::getAge) // 按年龄降序 .list(); } /** * 分页查询 */ @GetMapping("/page") public Page<User> getUserPage( @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size) { // 创建分页对象 Page<User> page = new Page<>(current, size); // 执行分页查询 return userService.page(page); } /** * 带条件的分页查询 */ @GetMapping("/page-with-condition") public Page<User> getUserPageWithCondition( @RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, @RequestParam(required = false) String keyword) { Page<User> page = new Page<>(current, size); return userService.lambdaQuery() .like(StringUtils.isNotBlank(keyword), User::getUsername, keyword) .page(page); } }

8. 更新操作

java

/** * 更新操作 */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; /** * 根据ID更新用户 */ @PutMapping public String updateUser(@RequestBody User user) { if (user.getId() == null) { return "用户ID不能为空"; } // 方法1:根据ID更新所有字段 boolean success = userService.updateById(user); return success ? "更新成功" : "更新失败"; } /** * 条件更新:将所有年龄小于18的用户年龄设置为18 */ @PutMapping("/fix-age") public String fixAge() { boolean success = userService.lambdaUpdate() .lt(User::getAge, 18) // age < 18 .set(User::getAge, 18) // 设置 age = 18 .update(); return success ? "年龄修复成功" : "年龄修复失败"; } /** * 部分字段更新 */ @PatchMapping("/{id}") public String partialUpdateUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) { // 移除不能更新的字段 updates.remove("id"); updates.remove("createTime"); boolean success = userService.updateById(id, updates); return success ? "部分更新成功" : "部分更新失败"; } }

9. 删除操作

java

/** * 删除操作 */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; /** * 根据ID删除用户(逻辑删除) */ @DeleteMapping("/{id}") public String deleteUser(@PathVariable Long id) { // 逻辑删除,实际上执行的是 update 操作,将 deleted 字段设置为 1 boolean success = userService.removeById(id); return success ? "删除成功" : "删除失败"; } /** * 批量删除 */ @DeleteMapping("/batch") public String batchDeleteUsers(@RequestBody List<Long> ids) { boolean success = userService.removeByIds(ids); return success ? "批量删除成功" : "批量删除失败"; } /** * 条件删除:删除所有年龄大于100的用户 */ @DeleteMapping("/old") public String deleteOldUsers() { boolean success = userService.lambdaUpdate() .gt(User::getAge, 100) // age > 100 .remove(); return success ? "删除老年用户成功" : "删除失败"; } }

高级特性

10. 自动填充功能

java

/** * 自动填充处理器 * 用于自动填充 createTime 和 updateTime */ @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()); } }

11. 分页插件配置

java

/** * MyBatis-Plus 配置类 */ @Configuration @MapperScan("com.yourpackage.mapper") // 指定Mapper接口的扫描路径 public class MybatisPlusConfig { /** * 分页插件配置 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 分页插件 PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); paginationInterceptor.setMaxLimit(1000L); // 设置最大单页限制数量 paginationInterceptor.setOverflow(true); // 超出最大页数后回到第一页 interceptor.addInnerInterceptor(paginationInterceptor); return interceptor; } }

12. 乐观锁插件配置

java

// 在 MybatisPlusConfig 中添加乐观锁插件 /** * 乐观锁插件配置 */ @Bean public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() { return new OptimisticLockerInnerInterceptor(); } // 实体类中配置乐观锁字段 @Version private Integer version;

13. 谨慎使用场景

1. 超复杂 SQL 场景

  • 涉及大量复杂联表查询
  • 需要高度优化的自定义 SQL
  • 复杂的存储过程调用

2. 性能要求极高的场景

  • 高并发写入场景
  • 需要精细控制 SQL 执行的场景

3. 遗留系统改造

  • 已有复杂 MyBatis 配置的项目
  • 数据库设计不符合 MP 规范

14. 不推荐使用场景

1. JPA 生态重度依赖项目

  • 已经深度使用 Spring Data JPA
  • 需要 JPA 的级联操作等特性

2. 非关系型数据库

  • MongoDB、Redis 等 NoSQL 数据库
  • 图数据库等特殊存储

最佳实践建议

15. 实体类设计规范

java

// 基础实体类 @Data public class BaseEntity { @TableId(type = IdType.AUTO) private Long id; @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; @TableLogic private Integer deleted; } // 业务实体类 @Data @EqualsAndHashCode(callSuper = true) @TableName("sys_user") public class User extends BaseEntity { private String username; private Integer age; private String email; // 数据库字段名与实体类字段名不一致时使用 @TableField("phone_number") private String phoneNumber; // 不映射到数据库的字段 @TableField(exist = false) private String temporaryCode; }

16. 服务层封装建议

java

// 好的服务层封装 @Service @Slf4j public class UserService extends ServiceImpl<UserMapper, User> { /** * 业务方法:用户注册 */ public boolean register(UserRegisterDTO registerDTO) { // 1. 校验用户名是否已存在 boolean exists = lambdaQuery() .eq(User::getUsername, registerDTO.getUsername()) .exists(); if (exists) { throw new RuntimeException("用户名已存在"); } // 2. DTO 转 Entity User user = new User(); BeanUtils.copyProperties(registerDTO, user); // 3. 保存用户 return save(user); } /** * 安全的更新方法 */ public boolean safeUpdate(User user) { if (user == null || user.getId() == null) { throw new IllegalArgumentException("用户ID不能为空"); } // 只更新非空字段 return lambdaUpdate() .eq(User::getId, user.getId()) .set(user.getUsername() != null, User::getUsername, user.getUsername()) .set(user.getAge() != null, User::getAge, user.getAge()) .set(user.getEmail() != null, User::getEmail, user.getEmail()) .update(); } }

17. 异常处理建议

java

/** * 全局异常处理 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { /** * 处理业务异常 */ @ExceptionHandler(BusinessException.class) public ResponseEntity<Result<?>> handleBusinessException(BusinessException e) { log.error("业务异常: {}", e.getMessage()); return ResponseEntity.badRequest().body(Result.error(e.getMessage())); } /** * 处理数据异常 */ @ExceptionHandler(DataAccessException.class) public ResponseEntity<Result<?>> handleDataAccessException(DataAccessException e) { log.error("数据访问异常: {}", e.getMessage()); return ResponseEntity.status(500).body(Result.error("数据操作失败")); } } /** * 统一返回结果 */ @Data public class Result<T> { private Integer code; private String message; private T data; public static <T> Result<T> success(T data) { Result<T> result = new Result<>(); result.setCode(200); result.setMessage("成功"); result.setData(data); return result; } public static <T> Result<T> error(String message) { Result<T> result = new Result<>(); result.setCode(500); result.setMessage(message); return result; } }

总结

工具是为人服务的,选择适合自己项目的技术栈才是最重要的。MyBatis-Plus 在大多数业务场景下都能显著提升开发效率,值得大家深入学习和使用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值