全面解析 Mybatis 与 Mybatis-Plus:深入原理、实践案例与高级特性对比

全面解析 Mybatis 与 Mybatis-Plus:深入原理、实践案例与高级特性对比 🚀

  • 前言
  • 一、基础介绍 ✨
    • 1. Mybatis 简介 🔍
    • 2. Mybatis-Plus 简介 ⚡
  • 二、核心区别与高级特性对比 🔎
    • 1. 开发模式与配置管理
    • 2. 功能丰富度与扩展性
    • 3. 自动填充与逻辑删除
    • 4. 性能监控与安全防护
  • 三、实战案例:构建用户管理系统与进阶功能演示 📚
    • 1. 案例一:基于 Mybatis 的用户管理系统
    • 2. 案例二:基于 Mybatis-Plus 的用户管理系统与进阶功能
  • 四、综合对比与实践中的注意事项 🎯
    • 1. 选择依据
    • 2. 开发实践建议
  • 五、总结 🌟


前言

在 Java 后端开发中,数据持久层始终是关键模块。如何既保证 SQL 调优的灵活性,又能提高开发效率,是众多开发者关注的焦点。本文将从基础介绍开始,全面解析 MybatisMybatis-Plus 的各个方面,包括工作原理、常见使用场景、详细实例、进阶特性、插件支持以及最佳实践,帮助你在项目中做出更明智的选择。让我们一起开始这段干货满满的技术之旅吧!💡

在这里插入图片描述


一、基础介绍 ✨

1. Mybatis 简介 🔍

Mybatis 是一款轻量级的 ORM 框架,它主要通过 XML 或注解方式将 SQL 语句与 Java 对象进行映射,具备以下特点:

  • 高度灵活

    开发者可以自定义 SQL,实现复杂查询及数据库操作。

  • 精细控制

    通过 XML 映射文件管理 SQL 与实体类之间的关系,充分掌控底层细节。

  • 低侵入性

    只关注数据库交互部分,业务逻辑完全由开发者掌控。

工作原理

  1. 映射配置:在 XML 文件或注解中定义 SQL 语句与参数映射。

  2. SqlSession 管理:通过 SqlSession 获取 Mapper 接口,完成数据库 CRUD 操作。

  3. 动态 SQL:支持动态 SQL 构建,便于处理复杂查询条件。

示例:Mybatis XML 配置

<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper"><select id="getUserById" resultType="com.example.entity.User">SELECT id, name, age FROM user WHERE id = #{id}</select>
</mapper>

虽然这种方式灵活、透明,但当项目中涉及大量 SQL 时,XML 文件的编写和维护会变得相对繁琐。😓

2. Mybatis-Plus 简介 ⚡

Mybatis-Plus 是在 Mybatis 基础上的增强工具包,旨在极大地简化开发流程,提高生产力。其主要特点包括:

  • 自动 CRUD

    内置 BaseMapper 接口,封装常用增删改查操作,省去重复编写 SQL。

  • 代码生成器

    通过代码生成快速构建实体类、Mapper 接口和 XML 映射文件。

  • 条件构造器

    提供链式调用方式构建查询条件(包括 Lambda 表达式方式),书写清晰直观。

  • 内置插件

    包括分页插件、性能分析插件、乐观锁、逻辑删除等常用功能。

  • 自动填充字段

    支持创建时间、修改时间等字段的自动填充,简化开发流程。

工作原理

  1. 自动封装:根据实体类和注解生成常用 SQL 语句,无需重复编写。

  2. 插件机制:通过插件扩展查询、更新、分页等功能,适应不同场景需求。

  3. 灵活扩展:支持自定义 SQL 和扩展方法,既满足快速开发又不失定制化能力。

示例:Mybatis-Plus 实体类与 Mapper 接口

// User.java
@Data
@TableName("user")
public class User {private Long id;private String name;private Integer age;
}// UserMapper.java
public interface UserMapper extends BaseMapper<User> {// 自定义方法示例:通过名字模糊查询用户List<User> selectByName(@Param("name") String name);
}

在 Spring Boot 项目中,只需简单配置数据源和包扫描即可快速启动应用。😊

二、核心区别与高级特性对比 🔎

1. 开发模式与配置管理

  • Mybatis

    • 配置方式:依赖 XML 或注解完成映射,代码与 SQL 分离,灵活但冗长。😅

    • 维护难度:每个实体或查询都需要单独配置,项目规模扩大时维护成本较高。

  • Mybatis-Plus

    • 约定优于配置:自动生成常用 SQL,极大减少了 XML 文件数量。💡

    • 自动化支持:内置自动 CRUD、分页和插件机制,使得配置更简洁、开发更高效。🚀

2. 功能丰富度与扩展性

  • Mybatis

    • 功能聚焦于 SQL 映射与执行,灵活定制性强,适合对 SQL 有极高要求的场景。

    • 支持动态 SQL,复杂业务逻辑处理能力突出。🔥

  • Mybatis-Plus

    • 自动 CRUD:BaseMapper 内置方法(如 selectByIdinsert 等)极大降低代码重复率。

    • 条件构造器:提供 QueryWrapperLambdaQueryWrapper,使用链式调用构建查询条件更加直观。

    • 插件体系:分页插件、乐观锁插件、性能分析插件等一应俱全,支持日志打印 SQL 执行时间,便于性能调优。😊

    示例:使用 Lambda 查询构造器

    // 查询名字中包含 "张" 的用户,年龄大于 20
    List<User> users = userMapper.selectList(new LambdaQueryWrapper<User>().like(User::getName, "张").gt(User::getAge, 20)
    );
    

3. 自动填充与逻辑删除

  • Mybatis-Plus 自动填充

    • 支持在插入或更新数据时自动填充常用字段(如 createTimeupdateTime)。

    • 通过自定义 MetaObjectHandler 实现字段自动更新,降低出错概率。

    示例:自动填充配置

    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", Timestamp.class, new Timestamp(System.currentTimeMillis()));this.strictInsertFill(metaObject, "updateTime", Timestamp.class, new Timestamp(System.currentTimeMillis()));}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", Timestamp.class, new Timestamp(System.currentTimeMillis()));// 强行更新updateTime// this.setFieldValByName("updateTime", new Timestamp(System.currentTimeMillis()), metaObject);}
    }
    
  • 逻辑删除

    • Mybatis-Plus 支持通过配置实现逻辑删除,数据不会真正从数据库删除,只是状态标记为已删除,更便于数据恢复和审计。

    • 只需在实体类上使用 @TableLogic 注解即可。

    示例:逻辑删除字段配置

    @Data
    @TableName("user")
    public class User {private Long id;private String name;private Integer age;@TableLogicprivate Integer deleted;
    }
    

4. 性能监控与安全防护

  • 性能分析插件

    • Mybatis-Plus 内置性能分析插件可帮助开发者在开发环境下检测 SQL 执行效率,提前发现慢查询问题。

    • 插件能够打印 SQL 语句及其执行时间,便于调优。😊

  • SQL 注入防护

    • 虽然 Mybatis 本身不会对 SQL 注入提供自动防护,但 Mybatis-Plus 在使用条件构造器时,通过参数化查询一定程度上降低了 SQL 注入风险。👍

三、实战案例:构建用户管理系统与进阶功能演示 📚

下面将通过两个案例,分别展示使用 Mybatis 与 Mybatis-Plus 实现用户管理系统的基本功能和进阶特性。

1. 案例一:基于 Mybatis 的用户管理系统

  • 环境配置与依赖

    • 依赖引入:在 Maven 中添加 Mybatis、Spring Boot、数据库驱动等依赖。

    • 配置文件:在 application.yml 中配置数据源和 Mybatis 映射文件路径。

    spring:datasource:url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8username: rootpassword: 123456
    mybatis:mapper-locations: classpath*:mapper/*.xml
    
  • Mapper XML 文件

    <!-- UserMapper.xml -->
    <mapper namespace="com.example.mapper.UserMapper"><select id="getUserById" resultType="com.example.entity.User">SELECT id, name, age FROM user WHERE id = #{id}</select><insert id="insertUser" parameterType="com.example.entity.User">INSERT INTO user(name, age) VALUES(#{name}, #{age})</insert><update id="updateUser" parameterType="com.example.entity.User">UPDATE user SET name = #{name}, age = #{age} WHERE id = #{id}</update><delete id="deleteUser" parameterType="Long">DELETE FROM user WHERE id = #{id}</delete>
    </mapper>
    
  • Service 与 Controller 层代码

    @Service
    public class UserService {@Autowiredprivate UserMapper userMapper;public User getUserById(Long id) {return userMapper.getUserById(id);}public void createUser(User user) {userMapper.insertUser(user);}public void updateUser(User user) {userMapper.updateUser(user);}public void deleteUser(Long id) {userMapper.deleteUser(id);}
    }@RestController
    @RequestMapping("/user")
    public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}@PostMapping("/")public String createUser(@RequestBody User user) {userService.createUser(user);return "创建成功!";}
    }
    

该案例展示了 Mybatis 灵活的映射机制,但随着业务复杂度增加,XML 文件和手动配置也会逐步增多。😓

2. 案例二:基于 Mybatis-Plus 的用户管理系统与进阶功能

  • 环境配置与依赖

    • 依赖引入:在 Maven 中添加 Mybatis-Plus Starter 及 Spring Boot 依赖。

    • 配置文件:基本与 Mybatis 类似,但无需编写大量 XML 文件。

    spring:datasource:url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8username: rootpassword: 123456
    mybatis-plus:mapper-locations: classpath*:mapper/*.xml
    
  • 实体类、Mapper 与自动填充

    // User.java@Data@TableName("user")public class User {private Long id;private String name;private Integer age;@TableLogicprivate Integer deleted;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;}// MyMetaObjectHandler.java@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", Timestamp.class, new Timestamp(System.currentTimeMillis()));this.strictInsertFill(metaObject, "updateTime", Timestamp.class, new Timestamp(System.currentTimeMillis()));}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", Timestamp.class, new Timestamp(System.currentTimeMillis()));// 强行更新updateTime// this.setFieldValByName("updateTime", new Timestamp(System.currentTimeMillis()), metaObject);}
    
  • Service 层与高级查询示例

    @Service
    public class UserService {@Autowiredprivate UserMapper userMapper;public User getUserById(Long id) {return userMapper.selectById(id);}public void createUser(User user) {userMapper.insert(user);}public void updateUser(User user) {userMapper.updateById(user);}public void deleteUser(Long id) {userMapper.deleteById(id);}// 进阶示例:使用 LambdaQueryWrapper 进行条件查询public List<User> getUsersByNameAndAge(String name, int age) {return userMapper.selectList(new LambdaQueryWrapper<User>().like(User::getName, name).ge(User::getAge, age));}
    }
    
  • Controller 层代码

    @RestController
    @RequestMapping("/user")
    public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}@PostMapping("/")public String createUser(@RequestBody User user) {userService.createUser(user);return "创建成功!";}@GetMapping("/search")public List<User> searchUsers(@RequestParam String name, @RequestParam int age) {return userService.getUsersByNameAndAge(name, age);}
    }
    

Mybatis-Plus 的优势在于减少重复代码、支持自动填充、逻辑删除以及内置的高级查询功能,既满足简单 CRUD,又能应对复杂查询场景。👍

四、综合对比与实践中的注意事项 🎯

1. 选择依据

  • 项目规模与复杂度

    • 对于简单或中小型项目,Mybatis-Plus 以其简洁高效的开发体验无疑更适合。

    • 大型或对 SQL 细节要求极高的系统,则可考虑 Mybatis,或结合使用二者,发挥各自优势。

  • 团队技术水平

    • 初学者更容易上手 Mybatis-Plus;

    • 资深开发者可根据实际需求灵活选择并扩展自定义功能。

2. 开发实践建议

  • 文档与社区

    • 阅读 Mybatis 和 Mybatis-Plus 的官方文档,关注最新插件和最佳实践;

    • 利用开源社区、博客(如 CSDN、掘金)中的经验分享,获取实际问题的解决方案。

  • 性能调优

    • 利用 Mybatis-Plus 的性能分析插件及时发现慢查询;

    • 在 Mybatis 中,合理使用动态 SQL 和缓存机制,优化数据库访问效率。

  • 安全性

    • 注意 SQL 注入问题,优先使用条件构造器和参数化查询;

    • 对于业务敏感数据,配置合理的事务管理和日志审计。


五、总结 🌟

通过本文的详细解析与丰富实例,了解到:

  • Mybatis 以其极高的灵活性和定制能力适合复杂业务场景,但配置与维护成本较高。

  • Mybatis-Plus 则在 Mybatis 基础上进行了功能扩展和自动化封装,极大提高了开发效率,适合快速开发中小型项目,同时也支持高级查询、自动填充和逻辑删除等特性。

未来,随着业务场景的不断丰富和技术的持续演进,选择合适的持久层框架将更注重团队开发效率和系统可维护性。

无论是坚持 Mybatis 的精细调优,还是选择 Mybatis-Plus 的自动化便利,深入理解底层原理和不断优化实践都是取得成功的关键!😊

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

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

相关文章

【区块链安全 | 第十九篇】类型之映射类型

文章目录 映射类型可迭代映射 映射类型 映射类型使用语法 mapping(KeyType KeyName? > ValueType ValueName?)&#xff0c;映射类型的变量声明使用语法 mapping(KeyType KeyName? > ValueType ValueName?) VariableName。 KeyType 可以是任何内置值类型、bytes、st…

动态循环表单+动态判断表单类型+动态判断表单是否必填方法

页面效果&#xff1a; 接口请求到的数据格式&#xff1a; list: [{demandType: "设备辅助功能要求",demandSettingList: [{id: "1907384788664963074",name: "测试表单",fieldType: 0,contentValue: "",vaildStatus: 0, // 0 非必填&a…

蓝桥杯DFS算法题(java)

最大连通 链接&#xff1a; https://www.lanqiao.cn/problems/2410/learning/ 问题描述 小蓝有一个 30 行 60 列的数字矩阵&#xff0c;矩阵中的每个数都是 0 或 1 。 1100100000111111101010010010011010101110110110111010011111100100000000010100011011000000100101100011…

解锁物种分布模拟新技能:MaxEnt 模型与 R 语言的奇妙融合

技术点目录 第二章、常用数据检索与R语言自动化下载及可视化方法第三章、R语言数据清洗与特征变量筛选第四章、基于ArcGIS、R数据处理与进阶第五章、基于Maxent的物种分布建模与预测第六章、基于R语言的模型参数优化第七章、物种分布模型结果分析与论文写作 —————————…

三轴云台之相机技术篇

一、结构设计 三轴云台通常由空间上三个互相垂直的框架构成&#xff0c;包括内框&#xff08;俯仰框&#xff09;、中框&#xff08;方位框&#xff09;和外框&#xff08;横滚框&#xff09;。这些框架分别负责控制相机的俯仰运动、方位运动和横滚运动&#xff0c;从而实现对目…

全文 - MLIR Toy Tutorial Chapter 3 :高层次上语言特定的分析和变换

使用 C 风格的模式匹配和重写来优化转置运算 使用 DRR 优化 reshape 运算 创建一种贴近输入语言的语义表示的方言&#xff0c;可以在 MLIR 中分析、变换和优化&#xff0c;这些过程中需要用到高级语言的信息&#xff0c;而且通常是在语言的 AST 上执行的这些过程。…

js逆向入门图灵爬虫练习平台 第四题学习

(base64解码&#xff09;地址:aHR0cHM6Ly9zdHUudHVsaW5ncHl0b24uY24vcHJvYmxlbS1kZXRhaWwvNC8 先找到请求接口带有加密参数&#xff1a; 全局搜索Sign,找到参数生成位置 看到这就一目了然塞&#xff0c;知道参数是怎么构造生成的&#xff0c;不知道这段 JavaScript 代码没关系…

【Flask开发】嘿马文学web完整flask项目第2篇:2.用户认证,Json Web Token(JWT)【附代码文档】

教程总体简介&#xff1a;2. 目标 1.1产品与开发 1.2环境配置 1.3 运行方式 1.4目录说明 1.5数据库设计 2.用户认证 Json Web Token(JWT) 3.书架 4.1分类列表 5.搜索 5.3搜索-精准&高匹配&推荐 6.小说 6.4推荐-同类热门推荐 7.浏览记录 8.1配置-阅读偏好 8.配置 9.1项目…

[dp5_多状态dp] 按摩师 | 打家劫舍 II | 删除并获得点数 | 粉刷房子

目录 1.面试题 17.16. 按摩师 题解 2.打家劫舍 II 题解 3.删除并获得点数 题解 4.粉刷房子 题解 一定要有这样的能力&#xff0c;碰到一个新题的时候&#xff0c;可以往之前做过的题方向靠&#xff01; 打家劫舍问题模型: 不能选择相邻的两个数&#xff0c;并且要最终…

基于javaweb的SSM羽毛球会员俱乐部系统场馆课程运动设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

windows下git bash安装SDKMan报错Looking for unzip...Not found

需要在jdk8和jdk17两个版本切换。最简单的是通过手动切换&#xff0c;但切换过程太繁琐&#xff0c;修改环境变量&#xff0c;达到切换目的。于是尝试其它解决方案&#xff0c;最终确实使用sdkman工具。 确保安装了git Git - Downloading Package 记住安装的路径&#xff0c;…

rnn的音频降噪背后技术原理

rnniose: 这个演示展示了 RNNoise 项目&#xff0c;说明了如何将深度学习应用于噪声抑制。其核心理念是将经典的信号处理方法与深度学习结合&#xff0c;打造一个小巧、快速的实时噪声抑制算法。它不需要昂贵的 GPU —— 在树莓派上就能轻松运行。 相比传统的噪声抑制系统&…

剑指Offer(数据结构与算法面试题精讲)C++版——day3

剑指Offer&#xff08;数据结构与算法面试题精讲&#xff09;C版——day3 题目一&#xff1a;数组中和为0的3个数字题目二&#xff1a;和大于或等于k的最短子数组题目三&#xff1a;乘积小于k的子数组 题目一&#xff1a;数组中和为0的3个数字 前面我们提到&#xff0c;在一个排…

全新UI好看404页面源码

源码介绍 全新UI好看404页面源码,源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行 效果预览 源码获取 全新UI好看404页面源码

递归典例---汉诺塔

https://ybt.ssoier.cn/problem_show.php?pid1205 #include<bits/stdc.h> #define endl \n #define pii pair<int,int>using namespace std; using ll long long;void move(int n,char a,char b,char c) // n 个盘子&#xff0c;通过 b&#xff0c;从 a 移动到 …

php的高速缓存

部署方法 在我们安装的nginx中默认不支持memc和srcache功能&#xff0c;需要借助第三方模块来让nginx支持此功能。 tar zxf srcache-nginx-module-0.33.tar.gz tar zxf memc-nginx-module-0.20.tar.gz 下载这俩个模块&#xff0c;然后编译安装的时候加进去 编译安装完成之后…

视频设备轨迹回放平台EasyCVR打造视频智能融合新平台,驱动智慧机场迈向数字新时代

一、行业背景​ 随着 5G、AI、物联网、大数据等前沿技术的不断更新换代&#xff0c;交通行业进入数字化转型的高速发展时期。航空业作为交通领域的重要部分&#xff0c;数字化进程从追求速度往注重质量的转变。但机场在数字化转型中面临许多严峻挑战&#xff0c;如现有运营模式…

【论文阅读】Anchor Graph Network for Incomplete Multiview Clustering

摘要 近年来&#xff0c;不完全多视图聚类&#xff08;IMVC&#xff09;受到广泛关注。然而&#xff0c;现有研究仍然存在以下几个不足之处&#xff1a;1) 部分方法忽略了样本对在全局结构分布中的关联性&#xff1b;2) 许多方法计算成本较高&#xff0c;因此无法应用于大规模…

15. 远程服务器运行jemter的GUI方式

1. 问题 在 linux 服务器或远程服务器上&#xff0c;安装 Jmeter&#xff0c;打不开 Jmeter 的 GUI 界面。 环境&#xff1a; linux 服务器mac 电脑 需求&#xff1a;在远程服务器中&#xff0c;启动 jmeter&#xff08;./bin/jmeter &&#xff09;后&#xff0c;在 ma…

Ansible:playbook的高级用法

文章目录 1. handlers与notify2. tags组件3. playbook中使用变量3.1使用 setup 模块中变量3.2在playbook 命令行中定义变量3.3在playbook文件中定义变量3.4使用变量文件3.5主机清单文件中定义变量主机变量组&#xff08;公共&#xff09;变量 1. handlers与notify Handlers&am…