Java ORM 代码量和性能对比:DoytoQuery vs SpringDataJPA/SpringJdbc/jOOQ/MyBatis-plus
TL;DR
代码量: DoytoQuery << SpringDataJPA/MyBatis-plus < jOOQ << SpringJdbc
查询性能:SpringJdbc > DoytoQuery > jOOQ >>> SpringDataJPA > MyBatis-plus
测试代码:https://github.com/f0rb/java-orm-comparison
介绍
本文基于几个常用的动态查询场景对比了基于对象查询映射(Object Query Mapping, OQM)方法的框架DoytoQuery与常用ORM框架(Spring Data JPA、Spring JDBC、jOOQ、MyBatis-plus)的代码量和查询性能。
实验设计
本实验旨在评估 DoytoQuery 与其他主流ORM框架在处理典型动态查询任务时的开发成本和运行效率。
实验对象
数据集来自Kaggle提供的工资数据 Data Science Salaries,共计 136,757 条记录。每条记录包含工作岗位、薪资、经验、工作类型、公司规模、工作地点等字段,适合构造多种复杂的动态查询场景。
对比框架
框架 | 简介 |
---|---|
DoytoQuery | OQM框架,通过声明式查询模型自动构建SQL语句 |
Spring Data JPA | Hibernate 封装的高层 ORM 框架 |
Spring JDBC | 基于 JDBC Template 的底层访问方式 |
jOOQ | 提供类型安全 SQL 构造的 DSL 框架 |
MyBatis-plus | MyBatis 增强工具,自动封装 CRUD |
查询场景
为了覆盖不同类型的查询逻辑,设计了以下三个查询任务:
编号 | 描述 |
---|---|
T1 | 查询 2025 年薪资在 20,000 和 100,000 之间的记录 |
URL | /salary/?workYear=2025&salaryInUsdGt=20000&salaryInUsdLt=100000&pageSize=10 |
SQL | SELECT * FROM salary WHERE work_year = ? AND salary_in_usd < ? AND salary_in_usd > ? LIMIT 10 OFFSET 0 |
T2 | 查询岗位为 "Researcher",薪资小于 30,000 或大于 300,000 的记录 |
URL | /salary/?jobTitle=Researcher&or.salaryInUsdLt=30000&or.salaryInUsdGt=300000&pageSize=10 |
SQL | SELECT * FROM salary WHERE job_title = ? AND (salary_in_usd < ? OR salary_in_usd > ?) |
T3 | 查询 2025 年薪资高于 2023 年最大薪资的记录 |
URL | /salary/?workYear=2025&salaryInUsdGt0.workYear=2023 |
SQL | SELECT * FROM salary WHERE work_year = ? AND salary_in_usd > (SELECT max(salary_in_usd) FROM salary WHERE work_year = ?) |
查询对象统一建模
为了保证对比公平,所有框架均通过统一的查询对象 SalaryQuery
实现参数处理:
public class SalaryQuery extends PageQuery { private Integer workYear; private String jobTitle; private Double salaryInUsdLt; private Double salaryInUsdGt; private SalaryQuery or; private SalaryQuery salaryInUsdGt0; }
评估指标
- 代码量(Code Size):统计方法代码行数与总体代码行数(LOC),评估代码维护成本。
- 性能(Performance):使用JMH测量每秒处理请求数量(ops/s),评估执行效率。
实验环境
-
硬件:
- CPU: Intel Core i5-13600KF
- 内存: 16GB DDR5
- 存储: 1TB SSD
- GPU: NVIDIA RTX 2060 Super
-
软件:
- 操作系统: Windows 11 Pro
- 数据库: MySQL 8.3.0
- JDK: Amazon Corretto 17.0.5
- Benchmark 工具: JMH 1.37
- 框架版本:Spring Boot 3.5.0、Spring Web 6.2.7 等
-
Benchmark 配置:
@BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) @State(Scope.Benchmark) @Fork(value = 2, jvmArgs = {"-Xms256M", "-Xmx2G", "-XX:+UseG1GC"}) @Threads(8) @Warmup(iterations = 8, time = 1) @Measurement(iterations = 3, time = 3) public class ORMBenchmark { /*...*/ }
实验结果
DQ: DoytoQuery JDBC: Spring JDBC JPA: Spring Data JPA MP: MyBatis-Plus
代码量对比
分析:
- DoytoQuery 基于声明式查询模型,无需编写动态查询构建方法,总代码量远低于其他框架。
- ORM框架都需要通过指令式编程构建SQL语句,构建动态查询的代码量相近。
这里仅对比了查询代码。如果需要实现完整的增删查改接口,Spring JDBC 需要自行拼接SQL语句,代码量最高;Spring Data JPA,jOOQ,MyBatis-Plus都封装了基本的增删查改语句构建,代码量次之;DoytoQuery实现了SQL语句的完全自动化构建,代码量最少。
总体来看,DoytoQuery在代码复用与简洁性上优于传统ORM框架。
性能对比
分析:
- Spring JDBC由于采用字符串拼接SQL,性能最佳。
- DoytoQuery与jOOQ性能其次。
- Spring Data JPA 和MyBatis-Plus的表现最弱。
总结
实验表明,OQM方法通过声明式查询模型自动构建SQL语句,在代码量上远低于ORM框架。同时,其运行性能接近Spring JDBC,并优于其他ORM框架,验证了OQM方法在实际应用中的可行性与优势。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
湖仓一体:小米集团基于 Apache Doris + Apache Paimon 实现 6 倍性能飞跃
企业在数据驱动的道路上,始终面临一对核心矛盾:既需要低成本、可扩展的存储方案来承载海量结构化、半结构化乃至非结构化数据(这正是数据湖的强项),又渴望实时、低延迟的分析能力来支撑业务决策(这是分析型数据库的核心优势)。 然而现实是,单独的解决方案往往难以两全:以 Apache Paimon 为代表的数据湖技术,虽凭借开放格式、弹性扩展和低成本存储成为企业数据中台的基石,但在低延迟响应上存在天然短板;而以 Apache Doris 为代表的分析型数据库,虽能提供高效的查询性能,却缺乏数据湖的存储灵活性与开放性。 本文的核心观点是:"架起数据库与数据湖的桥梁" 并非趋势,而是破局的关键。小米通过将 Apache Doris(数据库)与 Apache Paimon(数据湖)深度融合,不仅解决了数据湖分析的性能瓶颈,更实现了 "1+1>2" 的协同效应。 数据库与数据湖的互补之力 "桥接数据库与数据湖"的核心价值,在于构建"存储灵活、计算高效、格式协同 "的一体化架构------不仅是存储与计算能力的分工互补,更包含数据格式层面的深度协同,让两者的技术特性形成叠加效应。 1. 数据湖仓的分...
- 下一篇
如何批量杀死 Apache DolphinScheduler 运行中的工作流?
关键词: 大数据、数据调度、工作流、批量停止 整体说明 在调研了 DolphinScheduler 之后,在项目上实际使用了一段时间,遇到了任务过多僵死的问题,解决思路分享如下。 问题背景 任务依赖很多:从下图可以看出,有些任务的后续依赖很多,一旦失败,后续任务都得等待。这样就很容易导致后续任务被堵死。 循环任务很多,有很多任务本身是循环调用的其他任务的任务,会不停生成任务,循环任务本身也是任务,这就有可能导致任务堵死。 问题现象 就是很多任务,都在运行中的状态,但是就是不执行,因为他们占用了各自任务组的上限,导致卡死。当任务积累到一定程度,手工去杀死,太慢了,而且真的很累。 问题分析 我们现在就是要杀死这些任务,但是有一些要注意的点: 任务是全量任务,杀死不丢失数据: 只有全量任务,今天才能随意的去杀死,如果是增量的,就需要手工单独处理 下游任务今日不生成数据,不影响展示结果:下游的任务,或者说给客户展示的数据,这种高风险数据,不会因为今天的任务被杀死,而影响展示效果,数据一天不更新,不影响最终结果 解决方案 调用API批量杀死工作流:DolphinScheduler 是自带了很多的...
相关文章
文章评论
共有0条评论来说两句吧...