SpringBoot整合MyBatis-Plus:零XML实现高效CRUD

前言

作为一名开发者,数据库操作是我们日常工作中不可或缺的部分。传统的MyBatis虽然强大,但需要编写大量XML映射文件,这在快速开发的今天显得效率不足。MyBatis-Plus(简称MP)作为MyBatis的增强工具,在保留MyBatis所有特性的基础上,极大地简化了开发流程。本文将带你全面了解如何在SpringBoot项目中整合MyBatis-Plus,实现零XML配置的高效CRUD操作。

一、MyBatis-Plus简介:JPA vs MyBatis vs MyBatis-Plus

在开始整合之前,我们先了解下这三种持久层框架的特点和差异:

特性 JPA MyBatis MyBatis-Plus
ORM支持 全自动ORM 半自动ORM MyBatis增强
SQL控制 自动生成,可控性低 完全手动控制 自动生成+手动控制
XML配置 需要大量XML 零XML
CRUD操作 方法命名自动生成 需手动编写 内置通用Mapper
学习曲线 中等 较高 低(MyBatis基础上)
适用场景 简单标准业务 复杂SQL业务 各种业务场景

MyBatis-Plus的核心优势

  1. 无侵入:只做增强不做改变,引入它不会对现有工程产生影响

  2. 损耗小:启动即会自动注入基本CRUD,性能基本无损耗

  3. 强大CRUD:内置通用Mapper、通用Service,少量配置即可实现单表大部分CRUD操作

  4. 多种插件:支持分页、性能分析、乐观锁、逻辑删除等

二、SpringBoot整合MyBatis-Plus

1. 添加依赖

首先在pom.xml中添加必要依赖:

XML 复制代码
<!-- SpringBoot 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>

2. 配置数据库连接

application.yml中配置数据源和MyBatis-Plus相关配置:

XML 复制代码
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456

mybatis-plus:
  configuration:
    # 下划线转驼峰
    map-underscore-to-camel-case: true
    # 日志实现
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      # 主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID", UUID:"全局唯一UUID"
      id-type: auto
      # 逻辑删除字段名
      logic-delete-field: deleted
      # 逻辑删除值
      logic-delete-value: 1
      # 逻辑未删除值
      logic-not-delete-value: 0

三、实体类注解详解

MyBatis-Plus通过注解简化了实体类与数据库表的映射关系:

java 复制代码
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;

import java.util.Date;

@Data
@TableName("t_user")  // 指定表名,省略时默认使用类名作为表名
public class User {
    
    @TableId(type = IdType.AUTO)  // 主键自增
    private Long id;
    
    private String username;
    
    private String password;
    
    @TableField("real_name")  // 指定数据库字段名
    private String realName;
    
    private Integer age;
    
    private String email;
    
    @TableField(fill = FieldFill.INSERT)  // 插入时自动填充
    private Date createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)  // 插入和更新时自动填充
    private Date updateTime;
    
    @Version  // 乐观锁版本字段
    private Integer version;
    
    @TableLogic  // 逻辑删除字段
    private Integer deleted;
}

常用注解说明

  • @TableName:指定实体类对应的表名

  • @TableId:指定主键字段,可配置主键生成策略

  • @TableField:指定非主键字段与数据库列的映射关系

  • @Version:乐观锁注解

  • @TableLogic:逻辑删除注解

四、Mapper接口与Service层开发

1. 创建Mapper接口

java 复制代码
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;

public interface UserMapper extends BaseMapper<User> {
    // 继承BaseMapper后已包含基本CRUD方法
    // 可在此添加自定义SQL方法
}

2. Service层实现

MyBatis-Plus提供了通用的Service接口:

java 复制代码
public interface UserService extends IService<User> {
    // 可扩展自定义方法
}

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    // 实现类只需继承ServiceImpl即可
}

3. 基础CRUD示例

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    // 新增
    @PostMapping
    public boolean save(@RequestBody User user) {
        return userService.save(user);
    }
    
    // 删除
    @DeleteMapping("/{id}")
    public boolean remove(@PathVariable Long id) {
        return userService.removeById(id);
    }
    
    // 修改
    @PutMapping
    public boolean update(@RequestBody User user) {
        return userService.updateById(user);
    }
    
    // 查询单个
    @GetMapping("/{id}")
    public User getById(@PathVariable Long id) {
        return userService.getById(id);
    }
    
    // 分页查询
    @GetMapping("/page")
    public IPage<User> page(@RequestParam(defaultValue = "1") Integer current,
                           @RequestParam(defaultValue = "10") Integer size) {
        return userService.page(new Page<>(current, size));
    }
}

五、高级功能实战

1. 分页插件配置

MyBatis-Plus的分页功能需要先配置分页插件:

java 复制代码
@Configuration
public class MyBatisPlusConfig {
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

使用示例:

java 复制代码
// 基本分页
Page<User> page = new Page<>(1, 10);  // 当前页,每页大小
userMapper.selectPage(page, null);

// 自定义SQL分页
@Select("SELECT * FROM t_user WHERE age > #{age}")
IPage<User> selectPageByAge(IPage<User> page, @Param("age") Integer age);

2. 自动填充功能

实现MetaObjectHandler接口来处理自动填充字段:

java 复制代码
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
    }
    
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }
}

3. 条件构造器Wrapper

MyBatis-Plus提供了强大的条件构造器,可以构建复杂查询条件:

java 复制代码
// 查询年龄大于18且名字包含"张"的用户
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.gt(User::getAge, 18)
       .like(User::getUsername, "张");
List<User> users = userMapper.selectList(wrapper);

// 更新操作
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(User::getUsername, "张三")
             .set(User::getAge, 25);
userMapper.update(null, updateWrapper);

4. 逻辑删除配置

application.yml中已经配置了逻辑删除,实体类字段添加@TableLogic注解后,删除操作将自动变为更新操作:

java 复制代码
// 实际执行的是UPDATE t_user SET deleted=1 WHERE id=? AND deleted=0
userMapper.deleteById(1L);

// 查询时会自动加上WHERE deleted=0条件
userMapper.selectList(null);

5. 乐观锁实现

乐观锁通过版本号机制实现:

  1. 实体类添加@Version注解

  2. 配置乐观锁插件:

java 复制代码
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

使用示例:

java 复制代码
// 先查询获取version
User user = userMapper.selectById(1L);
// 修改数据
user.setUsername("new name");
// 执行更新,会带上version条件
userMapper.updateById(user);

六、性能优化建议

  1. 批量操作 :使用saveBatchupdateBatchById等方法提高批量操作效率

  2. SQL打印:开发环境可开启SQL打印方便调试,生产环境应关闭

  3. 索引优化:为常用查询条件添加数据库索引

  4. 查询字段控制 :避免使用select *,明确指定查询字段

  5. 逻辑删除:对于大表,逻辑删除可能影响性能,需考虑归档策略

七、常见问题解决方案

  1. 表名/字段名不一致

    • 使用@TableName@TableField注解明确指定

    • 配置全局的下划线转驼峰命名

  2. 主键策略问题

    • IdType.AUTO:数据库自增

    • IdType.ASSIGN_ID:雪花算法生成ID(默认)

    • IdType.ASSIGN_UUID:UUID生成

  3. 分页失效

    • 确保配置了分页插件

    • 检查Page参数是否正确传递

  4. 逻辑删除无效

    • 检查application.yml中的逻辑删除配置

    • 确保实体类字段添加了@TableLogic注解

结语

通过本文的介绍,相信你已经掌握了SpringBoot整合MyBatis-Plus的核心要点。MyBatis-Plus的强大功能可以让我们从繁琐的XML配置中解放出来,专注于业务逻辑的实现。在实际项目中,你可以根据需求组合使用各种功能,如分页+条件查询、逻辑删除+自动填充等,构建出高效可靠的数据访问层。

相关推荐
Lisonseekpan几秒前
Spring Boot 中使用 Caffeine 缓存详解与案例
java·spring boot·后端·spring·缓存
Terio_my1 小时前
Spring Boot Web环境测试配置
spring boot
汤姆yu1 小时前
2025版基于springboot的美食食品商城系统
spring boot·后端·美食
韩立学长1 小时前
【开题答辩实录分享】以《走失人口系统档案的设计与实现》为例进行答辩实录分享
mysql·mybatis·springboot
kfepiza2 小时前
Spring 如何解决循环依赖 笔记251008
java·spring boot·spring
Arva .3 小时前
Spring Boot 配置文件
java·spring boot·后端
IT_Octopus3 小时前
https私人证书 PKIX path building failed 报错解决
java·spring boot·网络协议·https
风象南4 小时前
从RBAC到ABAC的进阶之路:基于jCasbin实现无侵入的SpringBoot权限校验
spring boot·后端
小蒜学长4 小时前
jsp基于JavaWeb的原色蛋糕商城的设计与实现(代码+数据库+LW)
java·开发语言·数据库·spring boot·后端
摇滚侠4 小时前
Spring Boot中使用线程池来优化程序执行的效率!笔记01
java·spring boot·多线程