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的核心优势:
-
无侵入:只做增强不做改变,引入它不会对现有工程产生影响
-
损耗小:启动即会自动注入基本CRUD,性能基本无损耗
-
强大CRUD:内置通用Mapper、通用Service,少量配置即可实现单表大部分CRUD操作
-
多种插件:支持分页、性能分析、乐观锁、逻辑删除等
二、SpringBoot整合MyBatis-Plus
1. 添加依赖
首先在pom.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相关配置:
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mp_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456mybatis-plus:configuration:# 下划线转驼峰map-underscore-to-camel-case: true# 日志实现log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-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通过注解简化了实体类与数据库表的映射关系:
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接口
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接口:
public interface UserService extends IService<User> {// 可扩展自定义方法
}@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {// 实现类只需继承ServiceImpl即可
}
3. 基础CRUD示例
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;// 新增@PostMappingpublic boolean save(@RequestBody User user) {return userService.save(user);}// 删除@DeleteMapping("/{id}")public boolean remove(@PathVariable Long id) {return userService.removeById(id);}// 修改@PutMappingpublic 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的分页功能需要先配置分页插件:
@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}
使用示例:
// 基本分页
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
接口来处理自动填充字段:
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", Date.class, new Date());this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());}
}
3. 条件构造器Wrapper
MyBatis-Plus提供了强大的条件构造器,可以构建复杂查询条件:
// 查询年龄大于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
注解后,删除操作将自动变为更新操作:
// 实际执行的是UPDATE t_user SET deleted=1 WHERE id=? AND deleted=0
userMapper.deleteById(1L);// 查询时会自动加上WHERE deleted=0条件
userMapper.selectList(null);
5. 乐观锁实现
乐观锁通过版本号机制实现:
-
实体类添加
@Version
注解 -
配置乐观锁插件:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;
}
使用示例:
// 先查询获取version
User user = userMapper.selectById(1L);
// 修改数据
user.setUsername("new name");
// 执行更新,会带上version条件
userMapper.updateById(user);
六、性能优化建议
-
批量操作:使用
saveBatch
、updateBatchById
等方法提高批量操作效率 -
SQL打印:开发环境可开启SQL打印方便调试,生产环境应关闭
-
索引优化:为常用查询条件添加数据库索引
-
查询字段控制:避免使用
select *
,明确指定查询字段 -
逻辑删除:对于大表,逻辑删除可能影响性能,需考虑归档策略
七、常见问题解决方案
-
表名/字段名不一致:
-
使用
@TableName
和@TableField
注解明确指定 -
配置全局的下划线转驼峰命名
-
-
主键策略问题:
-
IdType.AUTO
:数据库自增 -
IdType.ASSIGN_ID
:雪花算法生成ID(默认) -
IdType.ASSIGN_UUID
:UUID生成
-
-
分页失效:
-
确保配置了分页插件
-
检查Page参数是否正确传递
-
-
逻辑删除无效:
-
检查
application.yml
中的逻辑删除配置 -
确保实体类字段添加了
@TableLogic
注解
-
结语
通过本文的介绍,相信你已经掌握了SpringBoot整合MyBatis-Plus的核心要点。MyBatis-Plus的强大功能可以让我们从繁琐的XML配置中解放出来,专注于业务逻辑的实现。在实际项目中,你可以根据需求组合使用各种功能,如分页+条件查询、逻辑删除+自动填充等,构建出高效可靠的数据访问层。
相关文章:
SpringBoot整合MyBatis-Plus:零XML实现高效CRUD
前言 作为一名开发者,数据库操作是我们日常工作中不可或缺的部分。传统的MyBatis虽然强大,但需要编写大量XML映射文件,这在快速开发的今天显得效率不足。MyBatis-Plus(简称MP)作为MyBatis的增强工具,在保留…...

python酒店健身俱乐部管理系统
目录 技术栈介绍具体实现截图系统设计研究方法:设计步骤设计流程核心代码部分展示研究方法详细视频演示试验方案论文大纲源码获取/详细视频演示 技术栈介绍 Django-SpringBoot-php-Node.js-flask 本课题的研究方法和研究步骤基本合理,难度适中…...

嵌入式开发学习(第二阶段 C语言基础)
综合案例《猜拳游戏》 需求: 本游戏是一款单机游戏,人机交互 规则: 需要双方出拳:石头、剪刀、布赢: 石头→剪刀剪刀→ 布布 →石头 两边出拳相等输: … 实现: 选择对手玩家出拳对手出拳判断胜…...
Easysearch 时序数据的基于时间范围的合并策略
如果你正在使用 Easysearch 处理日志、监控指标、事件流或其他任何具有时间顺序的数据,那么你一定知道索引的性能和效率至关重要。Easysearch 底层的 Lucene Segment 合并是保持搜索和索引性能的关键后台任务。然而,你是否意识到,默认的合并策…...
【C++】深入理解 unordered 容器、布隆过滤器与分布式一致性哈希
【C】深入理解 unordered 容器、布隆过滤器与分布式一致性哈希 在日常开发中,无论是数据结构优化、缓存设计,还是分布式架构搭建,unordered_map、布隆过滤器和一致性哈希都是绕不开的关键工具。它们高效、轻量,在性能与扩展性方面…...

YOLOv1:开启实时目标检测的新篇章
YOLOv1:开启实时目标检测的新篇章 在深度学习目标检测领域,YOLO(You Only Look Once)系列算法无疑占据着重要地位。其中,YOLOv1作为开山之作,以其独特的设计理念和高效的检测速度,为后续的目标…...
Spring Boot 整合 Redis 实战
一、整合准备:环境与依赖 1. 技术栈说明 Spring Boot 版本:3.1.2(兼容 Java 17) Redis 服务器:Redis 7.0(本地部署或 Docker 容器) Maven 依赖: <dependency><…...
Spring事务失效的全面剖析
文章目录 1. Spring事务基础1.1 什么是Spring事务1.2 Spring事务的实现原理1.3 `@Transactional`注解的主要属性1.4 使用Spring事务的简单示例2. Spring事务失效的常见场景及解决方案2.1 方法不是public的问题描述问题示例解决方案技术原理解释2.2 自调用问题(同一个类中的方法…...
Pytorch张量和损失函数
文章目录 张量张量类型张量例子使用概率分布创建张量正态分布创建张量 (torch.normal)正态分布创建张量示例标准正态分布创建张量标准正态分布创建张量示例均匀分布创建张量均匀分布创建张量示例 激活函数常见激活函数 损失函数(Pytorch API)L1范数损失函数均方误差损失函数交叉…...
消息~组件(群聊类型)ConcurrentHashMap发送
为什么选择ConcurrentHashMap? 在开发聊天应用时,我们需要存储和管理大量的聊天消息数据,这些数据会被多个线程频繁访问和修改。比如,当多个用户同时发送消息时,服务端需要同时处理这些消息的存储和查询。如果用普通的…...

FFmpeg多路节目流复用为一路包含多个节目的输出流
在音视频处理领域,将多个独立的节目流(如不同频道的音视频内容)合并为一个包含多个节目的输出流是常见需求。FFmpeg 作为功能强大的多媒体处理工具,提供了灵活的流复用能力,本文将通过具体案例解析如何使用 FFmpeg 实现…...

分子动力学模拟揭示点突变对 hCFTR NBD1结构域热稳定性的影响
囊性纤维化(CF) 作为一种严重的常染色体隐性遗传疾病,全球约有 10 万名患者深受其害。它会累及人体多个器官,如肺部、胰腺等,严重影响患者的生活质量和寿命。CF 的 “罪魁祸首” 是 CFTR 氯离子通道的突变,…...

关于SIS/DCS点检周期
在中国化工行业,近几年在设备维护上有个挺有意思的现象,即SIS和DCS这两个系统的点检周期问题,隔三差五就被管理层会议讨论,可以说是企业管理层关注的重要方向与关心要素。 与一般工业行业中设备运维不同,SIS与DCS的点…...
python-pyqt6框架工具开发总结
菜单栏 工具栏 状态栏 QTreeView 用于展示树形结构数据(模-视图框架),文件系统,组织结构 通常与QAbstractItemModel的子类(如QStandardItemModel或自动义模型) 展开/折叠 控制节点的显示状态,展开时显示子节点,折叠时隐藏子节点 s…...
Docker Volumes
Docker Volumes 是 Docker 提供的一种机制,用于持久化存储容器数据。与容器的生命周期不同,Volumes 可以独立存在,即使容器被删除,数据仍然保留。以下是关于 Docker Volumes 的详细说明: 1. 为什么需要 Volumes&#…...

【PmHub后端篇】PmHub中基于Redis加Lua脚本的计数器算法限流实现
1 限流的重要性 在高并发系统中,保护系统稳定运行的关键技术有缓存、降级和限流。 缓存通过在内存中存储常用数据,减少对数据库的访问,提升系统响应速度,如浏览器缓存、CDN缓存等多种应用层面。降级则是在系统压力过大或部分服务…...
FPGA实战项目2———多协议通信控制器
1. 多协议通信控制器模块 (multi_protocol_controller) 简要介绍 这是整个设计的顶层模块,承担着整合各个子模块的重要任务,是整个系统的核心枢纽。它负责协调 UART、SPI、I2C 等不同通信协议模块以及 DMA 模块的工作,同时处理不同时钟域之间的信号交互,确保各个模块能够…...

CST软件仿真案例——太阳能薄膜频谱吸收率
CST软件中的太阳能薄膜的功率吸收可用光频电磁波在介质材料中的损耗来计算。本案例计算非晶硅的功率吸收,然后考虑真实太阳频谱,计算有效吸收频谱。 用太阳能单元模板,时域求解器: 材料库提取四个材料,非晶硅…...
多线程进阶核心知识详解(通俗版)
Java多线程进阶详解 一、锁策略:如何高效管理资源竞争 在多线程环境中,锁是协调资源访问的核心机制。不同的锁策略适用于不同的场景,理解它们的差异能帮助优化程序性能。 1. 乐观锁 vs 悲观锁 悲观锁: 核心思想:假设…...
大模型中的KV Cache
1. KV Cache的定义与核心原理 KV Cache(Key-Value Cache)是一种在Transformer架构的大模型推理阶段使用的优化技术,通过缓存自注意力机制中的键(Key)和值(Value)矩阵,避免重复计算&…...
FHQ平衡树
FHQ平衡树 大致是这样的题目: 您需要动态地维护一个可重集合 M M M,并且提供以下操作: 向 M M M 中插入一个数 x x x。从 M M M 中删除一个数 x x x(若有多个相同的数,应只删除一个)。查询 M M M 中…...
力扣算法---总结篇
5.13 数组总结 数组是存放在连续内存空间上的相同类型数据的集合。 数组可以方便的通过下标索引的方式获取到下标对应的数据。 正是因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。 数组的元素是不…...

ABAP+旧数据接管的会计年度未确定
导资产主数据时,报错旧数据接管的会计年度未确定 是因为程序里面使用了下列函数AISCO_CALCULATE_FIRST_DAY,输入公司代码,获取会计年度,这个数据是在后台表T093C表中取数的,通过SE16N可以看到后台表数据没有数…...
Java【10_1】用户注册登录(面向过程与面向对象)
测试题 1、基于文本界面实现登录注册的需求(要求可以满足多个用户的注册和登录) 通过工具去完成 公共类: public class User { private int id;//用户编号 private int username;//用户名 private int password;//密码 private String name;//真…...

养生:打造健康生活的全方位策略
在生活节奏不断加快的当下,养生已成为提升生活质量、维护身心平衡的重要方式。从饮食、运动到睡眠,再到心态调节,各个方面的养生之道共同构建起健康生活的坚实基础。以下为您详细介绍养生的关键要点,助您拥抱健康生活。 饮食养生…...

贪吃蛇游戏排行榜模块开发总结:从数据到视觉的实现
一、项目背景与成果概览 在完成贪吃蛇游戏核心玩法后,本次开发重点聚焦于排行榜系统的实现。该系统具备以下核心特性: 🌐 双数据源支持:本地存储(localStorage)与远程API自由切换 🕒 时间维度统计:日榜/周榜/月榜/全时段数据筛选 🎮 模式区分:闯关模式(关卡进度…...
pytorch 数据预处理和常用工具
文章目录 NumPyNumpy数据结构安装和使用NumPy Matplotlib的安装和导入安装和导入Matplotlib绘制基础图画折线图散点图柱状图图例 数据清洗据清洗的作用Pandas进行数据清洗Pandas数据结构Series 数据结构DataFrame数据结构 Pandas数据清洗常用代码 特征工程主成分分析线性判别分…...
如何界定合法收集数据?
首席数据官高鹏律师团队 在当今数字化时代,数据的价值日益凸显,而合法收集数据成为了企业、机构以及各类组织必须严守的关键准则。作为律师,深入理解并准确界定合法收集数据的范畴,对于保障各方权益、维护法律秩序至关重要。 一…...
企业对数据集成工具的需求及 ETL 工具工作原理详解
当下,数据已然成为企业运营发展过程中的关键生产要素,其重要性不言而喻。 海量的数据分散在企业的各类系统、平台以及不同的业务部门之中,企业要充分挖掘这些数据背后所蕴含的巨大价值,实现数据驱动的精准决策,数据集…...
内核深入学习3——分析ARM32和ARM64体系架构下的Linux内存区域示意图与页表的建立流程
内核深入学习3——ARM32/ARM64在Linux内核中的实现(2) 今天我们来讨论的是一个硬核的内容,也是一个老生常谈的话题——那就是分析ARM32和ARM64体系架构下的Linux内存区域示意图的内容。对于ARM64的部分,我们早就知道一个基本的…...