MyBatis 与 MyBatis-Plus 的对比与选择

🔍 MyBatis 与 MyBatis-Plus 的对比与选择

文章目录

  • 🔍 MyBatis 与 MyBatis-Plus 的对比与选择
  • 🧠 一、MyBatis 核心回顾
    • 💡 核心思想与架构定位
    • ⚡ 基础使用示例
    • ⚠️ MyBatis 的痛点
  • ⚡ 二、MyBatis-Plus 功能特性解析
    • 💡 MyBatis-Plus 定位
    • 🚀 1. 单表 CRUD 封装
    • 🔧 2. 条件构造器(Wrapper)
    • 🛠️ 3. 插件体系
  • 🚀 三、代码生成与快速开发
    • 💡 代码生成器配置
    • ⚡ 生成结果结构
  • ⚖️ 四、全方位对比分析
    • 💡 核心特性对比
    • 📊 性能对比
    • 🔧 代码量对比
  • 🎯 五、适用场景与选型指南
    • 💡 技术选型决策框架
    • 🎯 具体场景建议
    • 📝 选型检查清单
  • 🔧 六、混合使用策略
    • 💡 共存与渐进式迁移
    • ⚡ 混合使用示例
    • 🔧 迁移策略建议
  • 🔚 总结与建议
    • 📚 核心结论
    • 🎯 最终建议

🧠 一、MyBatis 核心回顾

💡 核心思想与架构定位

MyBatis 作为半自动化的 ORM 框架,其设计哲学是:

SQL编写
MyBatis映射
Java对象

MyBatis 的核心价值​​:

  • 🎯 ​​SQL可控性​​:开发者完全掌握SQL优化
  • 🔧 ​​灵活性​​:支持复杂查询和存储过程
  • 📊 ​​映射简单​​:ResultMap实现对象关系映射
  • 🛡️ ​​稳定性​​:经过大量生产环境验证

⚡ 基础使用示例

// 传统MyBatis的Mapper接口
public interface UserMapper {@Select("SELECT * FROM users WHERE id = #{id}")User selectById(Integer id);@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id")int insert(User user);@Update("UPDATE users SET name=#{name} WHERE id=#{id}")int update(User user);@Delete("DELETE FROM users WHERE id = #{id}")int delete(Integer id);
}

XML 映射文件​​:

<!-- UserMapper.xml -->
<mapper namespace="com.example.mapper.UserMapper"><select id="selectByCondition" resultType="User">SELECT * FROM usersWHERE status = #{status}<if test="name != null">AND name LIKE CONCAT('%', #{name}, '%')</if>ORDER BY id DESC</select>
</mapper>

⚠️ MyBatis 的痛点

痛点描述影响
重复CRUD每个实体都需要基础CRUD方法开发效率低
SQL编写简单查询也需要手动编写SQL代码冗余
分页复杂需要插件或手动实现分页一致性差
代码生成缺乏官方代码生成工具初期搭建繁琐

⚡ 二、MyBatis-Plus 功能特性解析

💡 MyBatis-Plus 定位

MyBatis-Plus 是 MyBatis 的增强工具,在保留 MyBatis 所有特性的基础上,提供了更便捷的开发体验:

MyBatis
MyBatis-Plus
CRUD封装
条件构造器
代码生成器
插件体系

🚀 1. 单表 CRUD 封装

​​Mapper 接口继承​​:

// 只需继承BaseMapper即可获得完整CRUD能力
public interface UserMapper extends BaseMapper<User> {// 无需编写基础CRUD方法// 自定义复杂查询方法List<User> selectComplexQuery(UserQuery query);
}// 服务层使用
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public void addUser(User user) {// 直接使用MyBatis-Plus提供的方法int result = userMapper.insert(user);}public User getUserById(Long id) {return userMapper.selectById(id);}public List<User> getUsersByCondition() {// 使用QueryWrapper构建查询条件QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("status", 1).like("name", "张").orderByDesc("create_time");return userMapper.selectList(wrapper);}
}

🔧 2. 条件构造器(Wrapper)

​​Lambda 表达式条件构造​​:

// Lambda条件构造器(推荐)
public List<User> getActiveUsers(String keyword) {LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.eq(User::getStatus, 1).like(StringUtils.isNotBlank(keyword), User::getName, keyword).between(User::getCreateTime, startDate, endDate).orderByDesc(User::getCreateTime);return userMapper.selectList(wrapper);
}// 更新操作条件构造
public int updateUserStatus(Long userId, Integer status) {User user = new User();user.setStatus(status);UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.eq("id", userId).eq("status", 0); // 只更新状态为0的用户return userMapper.update(user, wrapper);
}

🛠️ 3. 插件体系

​​常用插件配置​​:

@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 分页插件PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();paginationInterceptor.setDbType(DbType.MYSQL);paginationInterceptor.setMaxLimit(1000L); // 单页最大条数interceptor.addInnerInterceptor(paginationInterceptor);// 乐观锁插件OptimisticLockerInnerInterceptor optimisticLockerInterceptor = new OptimisticLockerInnerInterceptor();interceptor.addInnerInterceptor(optimisticLockerInterceptor);return interceptor;}
}

​​分页查询示例​​:

public Page<User> getUsersByPage(int pageNum, int pageSize, UserQuery query) {Page<User> page = new Page<>(pageNum, pageSize);LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.eq(query.getStatus() != null, User::getStatus, query.getStatus()).like(StringUtils.isNotBlank(query.getKeyword()), User::getName, query.getKeyword());return userMapper.selectPage(page, wrapper);
}

🚀 三、代码生成与快速开发

💡 代码生成器配置

public class CodeGenerator {public static void main(String[] args) {AutoGenerator generator = new AutoGenerator();// 数据源配置DataSourceConfig dataSourceConfig = new DataSourceConfig();dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/test");dataSourceConfig.setUsername("root");dataSourceConfig.setPassword("123456");dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");generator.setDataSource(dataSourceConfig);// 全局配置GlobalConfig globalConfig = new GlobalConfig();globalConfig.setOutputDir(System.getProperty("user.dir") + "/src/main/java");globalConfig.setAuthor("Developer");globalConfig.setOpen(false);globalConfig.setSwagger2(true);generator.setGlobalConfig(globalConfig);// 包配置PackageConfig packageConfig = new PackageConfig();packageConfig.setParent("com.example");packageConfig.setEntity("entity");packageConfig.setMapper("mapper");packageConfig.setService("service");packageConfig.setController("controller");generator.setPackageInfo(packageConfig);// 策略配置StrategyConfig strategyConfig = new StrategyConfig();strategyConfig.setNaming(NamingStrategy.underline_to_camel);strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);strategyConfig.setEntityLombokModel(true);strategyConfig.setRestControllerStyle(true);strategyConfig.setInclude("user", "order"); // 要生成的表generator.setStrategy(strategyConfig);generator.execute();}
}

⚡ 生成结果结构

src/main/java/com/example/
├── entity/          # 实体类
│   ├── User.java
│   └── Order.java
├── mapper/         # Mapper接口
│   ├── UserMapper.java
│   └── OrderMapper.java
├── service/        # 服务接口
│   ├── IUserService.java
│   └── IOrderService.java
└── controller/     # 控制器├── UserController.java└── OrderController.java

⚖️ 四、全方位对比分析

💡 核心特性对比

特性MyBatisMyBatis-Plus优势方
CRUD操作手动编写自动封装MyBatis-Plus
条件构造手动拼接Lambda表达式MyBatis-Plus
代码生成需要插件官方生成器MyBatis-Plus
SQL控制完全控制部分封装MyBatis
学习曲线平缓稍陡峭MyBatis
灵活性中等MyBatis
开发效率MyBatis-Plus
社区生态成熟稳定活跃发展持平

📊 性能对比

场景MyBatisMyBatis-Plus说明
简单CRUD100ms95ms差异不大
复杂查询150ms160msMyBatis略优
分页查询依赖插件原生支持MyBatis-Plus更稳定
批量操作需要手动实现内置支持MyBatis-Plus更便捷

🔧 代码量对比

​​相同功能的实现代码量​​:

// MyBatis实现分页查询
public List<User> getUsersByPage(int pageNum, int pageSize, String keyword) {RowBounds rowBounds = new RowBounds((pageNum - 1) * pageSize, pageSize);return userMapper.selectUsersByKeyword(keyword, rowBounds);
}// MyBatis-Plus实现分页查询
public Page<User> getUsersByPage(int pageNum, int pageSize, String keyword) {Page<User> page = new Page<>(pageNum, pageSize);LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.like(StringUtils.isNotBlank(keyword), User::getName, keyword);return userMapper.selectPage(page, wrapper);
}

🎯 五、适用场景与选型指南

💡 技术选型决策框架

简单CRUD为主
复杂SQL需求
熟悉ORM框架
SQL能力强
新项目/快速迭代
遗留系统维护
项目需求分析
业务复杂度
MyBatis-Plus
MyBatis
团队技能水平
项目阶段

🎯 具体场景建议

​​推荐使用 MyBatis-Plus 的场景​​:

  1. ​​新项目启动​​:快速搭建基础CRUD功能
  2. 管理后台系统​​:大量表单和列表页面 ​​
  3. 微服务架构​​:需要快速开发数据访问层
  4. 团队技能一般​​:团队成员SQL能力较弱

​​推荐使用 MyBatis 的场景​​:

  1. 复杂业务系统​​:需要复杂SQL和存储过程 ​​
  2. 性能敏感场景​​:需要精细控制SQL优化
  3. ​​遗留系统维护​​:基于MyBatis的现有系统
  4. DBA严格管控​​:SQL需要DBA审核的场景

📝 选型检查清单

考虑因素MyBatisMyBatis-Plus
开发速度要求
SQL复杂度要求
团队学习成本
长期维护性
生态完整性
性能要求⚠️

🔧 六、混合使用策略

💡 共存与渐进式迁移

在实际项目中,可以采用混合使用策略:

现有MyBatis项目
引入MyBatis-Plus
新功能使用MyBatis-Plus
旧功能逐步迁移
完全迁移

⚡ 混合使用示例

// 传统MyBatis的Mapper
public interface UserMapper extends BaseMapper<User> {// MyBatis-Plus提供的CRUD方法// 自定义复杂查询(传统MyBatis方式)@Select("SELECT * FROM users WHERE create_time BETWEEN #{start} AND #{end}")List<User> selectByCreateTimeRange(@Param("start") Date start, @Param("end") Date end);// 使用MyBatis-Plus的条件构造器default List<User> selectByComplexCondition(UserQuery query) {LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();wrapper.eq(query.getStatus() != null, User::getStatus, query.getStatus()).ge(query.getStartTime() != null, User::getCreateTime, query.getStartTime()).le(query.getEndTime() != null, User::getCreateTime, query.getEndTime());return selectList(wrapper);}
}

🔧 迁移策略建议

  1. ​​初期​​:新功能使用 MyBatis-Plus,旧功能保持不动 ​​
  2. 中期​​:逐步将简单CRUD迁移到 MyBatis-Plus
  3. 后期​​:复杂功能评估后决定是否迁移

🔚 总结与建议

📚 核心结论

  1. ​​MyBatis​​:适合需要精细控制SQL、复杂查询场景
  2. ​​MyBatis-Plus​​:适合快速开发、简单CRUD为主的项目
  3. 混合使用​​:大多数现实项目的合理选择

🎯 最终建议

项目类型推荐方案理由
全新项目MyBatis-Plus开发效率高,功能全面
复杂系统MyBatisSQL控制精细,性能优化空间大
迁移项目混合策略平衡效率与风险
微服务MyBatis-Plus快速迭代,标准统一

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

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

相关文章

大数据-湖仓一体

数据仓库 这是一个传统的概念了&#xff0c;趋向于结构化数据&#xff0c;简单来说就是进过数据治理后的标准数据更易于数据分析使用&#xff0c;代价就是存储比较昂贵了 数据湖 近些年来新出的一种概念&#xff0c;就是存储了结构化&#xff0c;非结构化&#xff0c;半结构…

Java视觉跟踪入门:使用OpenCV实现实时对象追踪

视觉跟踪是计算机视觉领域的一个重要分支&#xff0c;它允许我们在视频序列中持续定位移动对象。本文将介绍如何使用Java和OpenCV库来实现一个简单的视觉跟踪系统。什么是视觉跟踪&#xff1f;视觉跟踪是指通过分析视频帧来自动追踪一个或多个移动对象的过程。这项技术广泛应用…

【题解 | 两种做法】洛谷 P4208 [JSOI2008] 最小生成树计数 [矩阵树/枚举]

特别难调&#xff0c;洛谷题解区很多人代码可读性不强&#xff0c;做的我怀疑人生。 &#xff08;虽然我的码风也一般就是了&#xff09; 前置知识&#xff1a; Kruskal 求最小生成树。 题面&#xff1a; 洛谷 P4208 两种做法&#xff0c;一种矩阵树一种枚举。 &#xff08…

光谱相机多层镀膜技术如何提高透过率

光谱相机多层镀膜技术通过精密的光学设计与材料组合实现透过率提升&#xff0c;其核心原理与技术特性如下&#xff1a;一、多层镀膜的光学优化机制‌复合相位调控‌ 通过交替沉积高折射率&#xff08;如TiO₂, n2.3&#xff09;与低折射率材料&#xff08;如SiO₂, n1.46&#…

ubantu安装配置hive

在Ubuntu系统上安装Hive通常涉及几个步骤&#xff0c;包括安装Java&#xff08;因为Hive依赖于Java&#xff09;&#xff0c;安装Hadoop&#xff0c;然后安装Hive本身。以下是一个基本的步骤指南&#xff1a; 安装Java 首先&#xff0c;确保你的系统上安装了Java。你可以通过运…

大模型RAG项目实战:文本向量模型>Embedding模型、Reranker模型以及ColBERT模型

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《GPT多模态大模型与AI Agent智能体》&#xff08;跟我一起学人工智能&#xff09;【陈敬雷编著】【清华大学出版社】 清华《GPT多模态大模型与AI Agent智能体》书籍配套视频课程【陈敬雷…

基于uni-app的校园综合服务平台开发实战

闪递校园&#xff1a;基于uni-app的校园综合服务平台开发实战作为一名全栈开发者&#xff0c;我用6个月时间开发了这款校园综合服务平台——闪递校园。本文将详细分享项目从0到1的开发经验&#xff0c;包括技术选型、核心功能实现、踩坑记录以及性能优化等方面的干货内容。&…

Qt::Q_INIT_RESOURCE用法

q_init_resource 用法 q_init_resource 是 Qt 框架中用于初始化嵌入式资源的一个函数。它通常用于将编译到应用程序二进制文件中的资源&#xff08;如图像、QML文件、翻译文件等&#xff09;注册到Qt的资源系统中。 基本用法 cpp Q_INIT_RESOURCE(resourcename); 其中 resource…

【开题答辩全过程】以 基于php的校园兼职求职网站为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

安卓悬浮球-3566-测试报告

安卓悬浮球-3566-测试报告 测试概述 项目名称: 悬浮球电子秤应用 测试版本: v1.0.0 测试时间: 2025年9月 测试环境: UniApp开发环境 测试类型: 功能测试、性能测试、兼容性测试 测试结果: 见附件测试环境配置 硬件环境 测试设备: Android 内置3566屏幕分辨率: 1080x1920内存: 2…

《C++进阶之STL》【红黑树】

【红黑树】目录前言&#xff1a;------------概念介绍------------1. 什么是红黑树&#xff1f;2. 红黑树的基本特性是什么&#xff1f;3. 红黑树的效率怎么样&#xff1f;4. 红黑树如何确保最长路径不超过最短路径的2倍&#xff1f;------------基本操作------------一、查找操…

Java全栈工程师的实战面试:从基础到微服务

Java全栈工程师的实战面试&#xff1a;从基础到微服务 在一次真实的面试中&#xff0c;一位经验丰富的Java全栈开发工程师被问及多个技术问题。他的名字是林浩然&#xff0c;28岁&#xff0c;拥有计算机科学与技术硕士学位&#xff0c;拥有5年的工作经验。他曾在一家大型互联网…

工业物联网(IIoT)+ AI:智能工业的未来趋势全解析

工业物联网&#xff08;IIoT&#xff09; AI&#xff1a;智能工业的未来趋势全解析 文章目录工业物联网&#xff08;IIoT&#xff09; AI&#xff1a;智能工业的未来趋势全解析摘要什么是工业物联网&#xff08;IIoT&#xff09;&#xff1f;1. IIoT 的定义2. IIoT 与传统 IoT …

3000. 对角线最长的矩形的面积

3000. 对角线最长的矩形的面积 题目链接&#xff1a;3000. 对角线最长的矩形的面积 代码如下&#xff1a; class Solution { public:int areaOfMaxDiagonal(vector<vector<int>>& dimensions) {double maxDiagonalLength 0;int res 0;for (vector<int&g…

Scikit-learn Python机器学习 - 什么是机器学习

锋哥原创的Scikit-learn Python机器学习视频教程&#xff1a; 2026版 Scikit-learn Python机器学习 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 课程介绍 本课程主要讲解基于Scikit-learn的Python机器学习知识&#xff0c;包括机器学习概述&#xff0c;特征工程(数据…

Python环境搭建报错

检查Python版本兼容性确保下载的Python版本与操作系统匹配&#xff08;如Windows 32位/64位、macOS ARM/x86&#xff09;。可通过命令行输入python --version或python3 --version验证已安装版本是否与需求一致。清理残留文件若之前安装失败&#xff0c;需手动删除残留文件。Win…

C# WinForm中提供webapi服务

云川给我提了一个需求&#xff0c;要我开发一个API服务程序&#xff0c;他来调用&#xff0c;程序再去明道云取数&#xff0c;计算出一个结果返回。网上找到了一篇文章&#xff1a;C# 在Windform程序中搭建Webapi - 小码哥-风云 - 博客园&#xff0c;可以使用微软提供的Microso…

Linux中使用docker部署solr

1. 运行一次&#xff0c;然后拉取镜像 [rootinstance-yo4hab98 ~]# docker run -d -p 8983:8983 --name solr-8.11.3 -t solr:8.11.3 ps 镜像相关指令 # 查看镜像 docker images# 删除镜像 指定名称和版本删除 docker rmi nginx:latest # 删除镜像 指定id删除 docker rm…

代谢组学分析指南

摘要代谢组学是个新兴领域&#xff0c;系统性地定量众多代谢物。关键目的是识别与每种生物表型相对应的代谢物&#xff0c;并进一步分析其中涉及的机制。尽管代谢组学对于理解相关的生物学现象至关重要&#xff0c;但在全面描述过程的能力上存在局限性。推荐采用综合分析策略&a…

vue2使用el-form动态参数展示并非空校验

需求&#xff1a;需要根据类型type动态显示某些参数&#xff0c;并且后端需要的参数也不同&#xff0c;比如type为1&#xff1a;后端要aa和bb参数&#xff0c;type为2&#xff1a;后端要cc和dd参数&#xff0c;前端显示的字段名也不一样&#xff0c;但是样式是不变的。1.效果2.…