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

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

特性JPAMyBatisMyBatis-Plus
ORM支持全自动ORM半自动ORMMyBatis增强
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中添加必要依赖:

<!-- 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. 乐观锁实现

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

  1. 实体类添加@Version注解

  2. 配置乐观锁插件:

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

六、性能优化建议

  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配置中解放出来,专注于业务逻辑的实现。在实际项目中,你可以根据需求组合使用各种功能,如分页+条件查询、逻辑删除+自动填充等,构建出高效可靠的数据访问层。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80657.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringCloud之Gateway基础认识-服务网关

0、Gateway基本知识 Gateway 是在 Spring 生态系统之上构建的 API 网关服务&#xff0c;基于 Spring &#xff0c;Spring Boot 和 Project Reactor 等技术。 Gateway 旨在提供一种简单而有效的方式来对 API 进行路由&#xff0c;以及提供一些强大的过滤器功能&#xff0c;例如…

Redis扫盲

Redis 缓存中间件 基础篇 键值数据库 key Value 是NoSql数据库 非结构化、无关联的、非SQL、BASE&#xff08;无法满足ACID&#xff09; 命令执行是单线程&#xff0c;符合原子性。 低延迟、速度块&#xff08;基于内存&#xff0c;IO多路复用&#xff0c;良好的编码&am…

【FMMT】基于模糊多模态变压器模型的个性化情感分析

遇到很难的文献看不懂,不应该感到气馁,应该激动,因为外审估计也看不太懂,那么学明白了可以吓唬他 缺陷一:输入依赖性与上下文建模不足​​ ​​缺陷描述​​: 传统自注意力机制缺乏因果关系,难以捕捉序列历史背景多模态数据间的复杂依赖关系未被充分建模CNN/RNN类模型在…

Qt Creator 配置 Android 编译环境

Qt Creator 配置 Android 编译环境 环境配置流程下载JDK修改Qt Creator默认android配置文件修改sdk_definitions.json配置修改的内容 Qt Creator配置 异常处理删除提示占用编译报错连接安卓机调试APP闪退无法进入 debug 断点 环境 Qt Creator 版本 qtcreator-16.0.1Win10 嗯, …

使用聊天模型和提示模板构建一个简单的 LLM 应用程序

官方教程 官方案例 在上面的链接注册后&#xff0c;请确保设置您的环境变量以开始记录追踪 export LANGSMITH_TRACING"true" export LANGSMITH_API_KEY"..."或者&#xff0c;如果在笔记本中&#xff0c;您可以使用以下命令设置它们 import getpass imp…

React vs Vue:点击外部事件处理的对比与实现

React vs Vue&#xff1a;点击外部事件处理的对比与实现 在 Web 应用中&#xff0c;“点击外部事件监听”是一种常见需求&#xff0c;典型应用如&#xff1a;点击弹窗外部关闭弹窗、点击下拉菜单外关闭菜单。虽然在 React 和 Vue 中实现的原理类似——都是通过监听 document 的…

3335. 字符串转换后的长度 I

3335. 字符串转换后的长度 I class Solution:def lengthAfterTransformations(self, s: str, t: int) -> int:# 大质数mod 10**97# 创建一个长度为26的数组cnt&#xff0c;对应26个小写字母cnt [0]*26# 计算出s中26个字符分别有多少个for ch in s:cnt[ord(ch)-ord(a)] 1f…

Java详解LeetCode 热题 100(15):LeetCode 189. 轮转数组(Rotate Array)详解

文章目录 1. 题目描述2. 理解题目3. 解法一&#xff1a;使用额外数组3.1 思路3.2 Java代码实现3.3 代码详解3.4 复杂度分析3.5 适用场景 4. 解法二&#xff1a;环状替换法&#xff08;原地算法&#xff09;4.1 思路4.2 Java代码实现4.3 代码详解4.4 复杂度分析4.5 陷阱与注意事…

数据治理域——日志数据采集设计

摘要 本文主要介绍了Web页面端日志采集的设计。首先阐述了页面浏览日志采集&#xff0c;包括客户端日志采集的实现方式、采集内容及技术亮点。接着介绍了无线客户端端日志采集&#xff0c;包括UserTrack的核心设计、移动端与浏览器端采集差异以及典型应用场景崩溃分析。最后探…

PYTHON训练营DAY24

# SO代码我们的感情好像跳楼机 # 元组创建时&#xff0c;可以省略括号&#xff1a;my_tuple4 10, 20, thirty # 字符串要加“ ” 元组 一、创建 my_tuple1 (1, 2, 3) my_tuple2 (a, b, c) my_tuple3 (1, hello, 3.14, [4, 5]) # 可以包含不同类型的元素 print(my_tupl…

超声波传感器模块

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 1.HC-SR04介绍2.HC-SR04原理介绍2.1原理概述3.2原理详解 4驱动代码编写4.1写前思考4.2硬件连线 5.总结hcsr04.hhcsr04.c 1.HC-SR04介绍 超声波传感器有很多种类的型号&#xff1a;HC-SR04、UC-025、…

《Effective Python》第2章 字符串和切片操作——深入理解Python 中的字符数据类型(bytes 与 str)的差异

引言 本篇博客基于学习《Effective Python》第三版 Chapter 2: Strings and Slicing 中的 Item 10: Know the Differences Between bytes and str 的总结与延伸。在 Python 编程中&#xff0c;字符串处理是几乎每个开发者都会频繁接触的基础操作。然而&#xff0c;Python 中的…

py7zr解压文件时报错CrcError(crc32, f.crc32, f.filename)

报错信息 Traceback (most recent call last):File "/home/hp/project/test/file_util.py", line 130, in extract_archive_7zarchive.extract(targets[fixed_file], pathoutput_dir, recursiveTrue)File "/home/hp/miniconda3/envs/celery/lib/python3.10/sit…

物理:由基本粒子组成的个体能否提炼和重组?

个体差异源于基本粒子组合的复杂性与随机性,这一假设若成立,确实可能为生物医学带来革命性突破——但需要突破技术、理论与系统层级的多重壁垒。以下从科学逻辑与技术路径展开分析: 一、随机组合中的共性与稳定结构 1. 自然界的自组织规律 涌现性(Emergence):尽管粒子组…

动态路由EIGRP的配置

动态路由EIGRP的配置 动态路由EIGRP&#xff1a;增强内部网关协议 为何收敛快、不成环&#xff1f; 路由计算的无环路和路由的收敛速度是路由计算的重要指标。EIGRP协议由于使用了DUAL算法&#xff0c;使得EIGRP协议在路由计算中不可能有环路路由产生&#xff0c;同时路由计…

组合问题(多条件)

39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; class Solution { private:vector<vector<int>>result;vector<int>path;void backtracking(vector<int>& candidates, int target,int sum,int startIndex){if(sum>target){return;}if(…

SimScape物理建模实例2--带控制的单质量弹簧阻尼系统

模型下载&#xff1a; 基于simscape&#xff0c;单质量系统带位置控制资源-CSDN文库 在实例1中&#xff0c;我们搭建了不带控制的单质量弹簧阻尼系统&#xff0c;该系统没有外界力量介入&#xff0c;只有弹簧的初始弹力&#xff0c;带着弹簧使劲弹来弹去。 SimScape物理建模实…

OpenAI Text 模型与 Chat 模型调用实战指南:从基础配置到创意花店命名

在 AI 应用开发的浪潮中&#xff0c;OpenAI 的大语言模型成为开发者实现创新功能的得力工具。其中&#xff0c;Text 模型和 Chat 模型作为核心接口&#xff0c;被广泛应用于文本生成、对话交互等场景。本文将以 “为花店起名” 为实际需求&#xff0c;手把手教你如何安全调用这…

网页常见水印实现方式

文章目录 1 明水印技术实现1.1 DOM覆盖方案1.2 Canvas动态渲染1.3 CSS伪元素方案2 暗水印技术解析2.1 空域LSB算法2.2 频域傅里叶变换3 防篡改机制设计3.1 MutationObserver防护3.2 Canvas指纹追踪4 前后端实现对比5 攻防博弈深度分析5.1 常见破解手段5.2 进阶防御策略6 选型近…

现代化QML组件开发教程

现代化QML组件开发教程 目录 QML基础介绍QML项目结构基本组件详解自定义组件开发状态与过渡高级主题最佳实践 QML基础介绍 什么是QML QML (Qt Meta Language) 是一种声明式语言&#xff0c;专为用户界面设计而创建。它是Qt框架的一部分&#xff0c;让开发者能够创建流畅、…