很多小伙伴不太了解ORM框架的底层原理,这不,冰河带你10分钟手撸一个极简版ORM框架(赶快收藏吧)

article/2025/10/19 7:47:26

大家好,我是冰河~~

最近很多小伙伴对ORM框架的实现很感兴趣,不少读者在冰河的微信上问:冰河,你知道ORM框架是如何实现的吗?比如像MyBatis和Hibernate这种ORM框架,它们是如何实现的呢?

为了能够让小伙伴们更加深刻并且清晰的理解ORM框架的实现原理,冰河决定自己手撸一个极简版的ORM框架,让小伙伴们一看就能够明白什么是ORM框架?ORM框架到底是如何运行的?ORM框架是如何将程序对象与数据库中的数据进行映射的?不过,在正式开始手撸ORM框架之前,我们要先来搞清楚什么是ORM框架。

什么是ORM框架?

ORM全称为:Object Relational Mapping,翻译成中文就是:对象关系映射。也就是说ORM框架就是对象关系映射框架,它通过元数据描述对象与关系映射的细节,ORM框架在运行的时候,可以根据对应与映射之间的关系将数据持久化到数据库中。

其实,从本质上讲,ORM框架主要实现的是程序对象到关系数据库数据的映射。说的直白点:ORM框架就是将实体和实体与实体之间的关系,转化为对应的SQL语句,通过SQL语句操作数据库,将数据持久化到数据库中,并且对数据进行相应的增删改查操作。

最常用的几种ORM框架为:MyBatis、Hibernate和JFinal。

手撸ORM框架

这里,我们模拟的是手撸Hibernate框架实现ORM,小伙伴们也可以模拟其他的ORM框架实现,核心原理都是相通的。如果大家在模拟其他框架手撸实现ORM时,遇到问题的话,都可以私聊我沟通,我看到的话,会第一时间回复大家。

好了,说干就干,我们开始吧。

@Table注解的实现

首先,我们创建一个io.mykit.annotation.jdk.db.provider Java包,在这个Java包创建一个@Table注解,@Table注解标注在Java类上,表示当前类会被映射到数据库中的哪张数据表上,如下所示。

package io.mykit.annotation.jdk.db.provider;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*** 自定义Table注解* @author binghe**/
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Table {String value() default "";
}

@Column注解的实现

同样的,在io.mykit.annotation.jdk.db.provider包下创建一个@Column注解,@Column注解标注在类中的字段上,表示当前类中的字段映射到数据表中的哪个字段上,如下所示。

package io.mykit.annotation.jdk.db.provider;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 自定义Column注解* @author binghe**/
@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Column {String value() default "";
}

看到这里,不管是使用过MyBatis的小伙伴还是使用过Hibernate的小伙伴,应该都会有所体会吧?没错,@Table注解和@Column注解,不管是在MyBatis框架还是Hibernate框架中,都会被使用到。这里,我们在收录极简版ORM框架时,也使用了这两个经典的注解。

创建实体类

io.mykit.annotation.jdk.db.provider.entity包下创建实体类User,并且@Table注解和@Column注解会被分别标注在User类上和User类中的字段上,将其映射到数据库中的数据表和数据表中的字段上,如下所示。

package io.mykit.annotation.jdk.db.provider.entity;import io.mykit.annotation.jdk.db.provider.Column;
import io.mykit.annotation.jdk.db.provider.Table;/*** 自定义使用注解的实体* @author binghe**/
@Table("t_user")
public class User implements Serializable{@Column("id")private String id;@Column("name")private String name;public User() {super();}public User(String id, String name) {super();this.id = id;this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "User [id=" + id + ", name=" + name + "]";}}

注解解析类的实现

io.mykit.annotation.jdk.db.provider.parser包中创建一个AnnotationParser类,AnnotationParser 类是整个框架的核心,它负责解析标注在实体类上的注解,并且将对应的实体类及其字段信息映射到对应的数据表和字段上,如下所示。

package io.mykit.annotation.jdk.db.provider.parser;import java.lang.reflect.Field;
import java.lang.reflect.Method;import io.mykit.annotation.jdk.db.provider.Column;
import io.mykit.annotation.jdk.db.provider.Table;/*** 解析自定义注解* @author binghe**/
public class AnnotationParser {/** * 通过注解来组装查询条件,生成查询语句 * @param obj * @return */  public static String assembleSqlFromObj(Object obj) {  Table table = obj.getClass().getAnnotation(Table.class);  StringBuffer sbSql = new StringBuffer();  String tableName = table.value();  sbSql.append("select * from " + tableName + " where 1=1 ");  Field[] fileds = obj.getClass().getDeclaredFields();  for (Field f : fileds) {  String fieldName = f.getName();  String methodName = "get" + fieldName.substring(0, 1).toUpperCase()  + fieldName.substring(1);  try {  Column column = f.getAnnotation(Column.class);  if (column != null) {  Method method = obj.getClass().getMethod(methodName);  Object v = method.invoke(obj);  if (v != null) {  if (v instanceof String) {  String value = v.toString().trim();// 判断参数是不是 in 类型参数 1,2,3  if (value.contains(",")) {  //去掉value中的,String sqlParams = value.replace(",", "").trim();//value中都是纯数字if(isNum(sqlParams)){sbSql.append(" and " + column.value() + " in (" + value + ") ");  }else{String[] split = value.split(",");//将value重置为空value = "";for(int i = 0; i < split.length - 1; i++){value += "'"+split[i]+"',";}value += "'"+split[split.length - 1]+"'";sbSql.append(" and " + column.value() + " in (" + value + ") ");  }} else {  if(value != null && value.length() > 0){sbSql.append(" and " + column.value() + " like '%" + value + "%' ");  }}  } else {sbSql.append(" and " + column.value() + "=" + v.toString() + " ");  }  }  }  } catch (Exception e) {  e.printStackTrace();  }  }  return sbSql.toString();  }  /** * 检查给定的值是不是 id 类型 1.检查字段名称 2.检查字段值 *  * @param target * @return */  public static boolean isNum(String target) {  boolean isNum = false;  if (target.toLowerCase().contains("id")) {  isNum = true;  }  if (target.matches("\\d+")) {  isNum = true;  }  return isNum;  }  
}

至此,我们的极简版ORM框架就实现好了,不过实现完还不行,我们还要对其进行测试验证。

测试类的实现

io.mykit.annotation.jdk.provider包下创建AnnotationTest 类,用以测试我们实现的极简ORM框架的效果,具体如下所示。

package io.mykit.annotation.jdk.provider;import org.junit.Test;import io.mykit.annotation.jdk.db.provider.entity.User;
import io.mykit.annotation.jdk.db.provider.parser.AnnotationParser;
import io.mykit.annotation.jdk.provider.parser.AnnotationProcessor;/*** 测试自定义注解* @author binghe**/
public class AnnotationTest {@Testpublic void testDBAnnotation(){User testDto = new User("123", "34");  User testDto1 = new User("123", "test1");  User testDto2 = new User("", "test1,test2,test3,test4");  String sql = AnnotationParser.assembleSqlFromObj(testDto);  String sql1 = AnnotationParser.assembleSqlFromObj(testDto1);  String sql2 = AnnotationParser.assembleSqlFromObj(testDto2);  System.out.println(sql);  System.out.println(sql1);  System.out.println(sql2);  }
}

运行测试

我们运行AnnotationTest#testDBAnnotation()方法,命令行会输出如下信息。

select * from t_user where 1=1  and id like '%123%'  and name like '%34%' 
select * from t_user where 1=1  and id like '%123%'  and name like '%test1%' 
select * from t_user where 1=1  and name in ('test1','test2','test3','test4') 

可以看到,我们在测试程序中,并没有在测试类中传入或者执行任何SQL语句,而是直接创建User类的对象,并调用AnnotationParser#assembleSqlFromObj()进行解析,并且将对应的实体类对象转换为SQL语句返回。

其实,MyBatis和Hibernate的底层核心原理都是这样的,大家学会了吗?有不懂的地方欢迎私聊我沟通。赶紧打开你的开发环境,手撸个极简版ORM框架吧!!

大家有啥问题可以在下方留言,如果文章对你有点帮助,欢迎转发给更多的小伙伴~~

好了,今天就到这儿吧,我是冰河,我们下期见~~

写在最后

如果你想进大厂,想升职加薪,或者对自己现有的工作比较迷茫,都可以私信我交流,希望我的一些经历能够帮助到大家~~

推荐阅读:

  • 《实践出真知:全网最强秒杀系统架构解密,不是所有的秒杀都是秒杀!!》
  • 《从零到上亿用户,我是如何一步步优化MySQL数据库的?(建议收藏)》
  • 《我用多线程进一步优化了亿级流量电商业务下的海量数据校对系统,性能再次提升了200%!!(全程干货,建议收藏)》
  • 《我用多线程优化了亿级流量电商业务下的海量数据校对系统,性能直接提升了200%!!(全程干货,建议收藏)》
  • 《我用10张图总结出了这份并发编程最佳学习路线!!(建议收藏)》
  • 《高并发场景下一种比读写锁更快的锁,看完我彻底折服了!!(建议收藏)》
  • 《全网最全性能优化总结!!(冰河吐血整理,建议收藏)》
  • 《三天撸完了MyBatis,各位随便问!!(冰河吐血整理,建议收藏)》
  • 《奉劝那些刚参加工作的学弟学妹们:要想进大厂,这些并发编程知识是你必须要掌握的!完整学习路线!!(建议收藏)》
  • 《奉劝那些刚参加工作的学弟学妹们:要想进大厂,这些核心技能是你必须要掌握的!完整学习路线!!(建议收藏)》
  • 《奉劝那些刚参加工作的学弟学妹们:这些计算机与操作系统基础知识越早知道越好!万字长文太顶了!!(建议收藏)》
  • 《我用三天时间开发了一款老少皆宜的国民级游戏,支持播放音乐,现开放完整源代码和注释(建议收藏)!!》
  • 《我是全网最硬核的高并发编程作者,CSDN最值得关注的博主,大家同意吗?(建议收藏)》
  • 《毕业五年,从月薪3000到年薪百万,我掌握了哪些核心技能?(建议收藏)》
  • 《我入侵了隔壁妹子的Wifi,发现。。。(全程实战干货,建议收藏)》
  • 《千万不要轻易尝试“熊猫烧香”,这不,我后悔了!》
  • 《清明节偷偷训练“熊猫烧香”,结果我的电脑为熊猫“献身了”!》
  • 《7.3万字肝爆Java8新特性,我不信你能看完!(建议收藏)》
  • 《在业务高峰期拔掉服务器电源是一种怎样的体验?》
  • 《全网最全Linux命令总结!!(史上最全,建议收藏)》
  • 《用Python写了个工具,完美破解了MySQL!!(建议收藏)》
  • 《SimpleDateFormat类到底为啥不是线程安全的?(附六种解决方案,建议收藏)》
  • 《MySQL 8中新增的这三大索引,直接让MySQL起飞了,你竟然还不知道!!(建议收藏)》
  • 《撸完Spring源码,我开源了这个分布式缓存框架!!(建议收藏)》
  • 《亿级流量高并发秒杀系统商品“超卖”了,只因使用的JDK同步容器中存在这两个巨大的坑!!(踩坑实录,建议收藏)》
  • 《奉劝那些刚参加工作的学弟学妹们:要想学好并发编程,这些并发容器的坑是你必须要注意的!!(建议收藏)》
  • 《公司的报表工具太难用,我三天撸了个Excel工具,运营小姐姐直呼太好用了,现已开源!!(建议收藏)》
  • 《奉劝那些刚参加工作的学弟学妹们:要想进大厂,这些并发编程核心技能是你必须要掌握的!!(建议收藏)》
  • 《阿里面试官:高并发大流量秒杀系统如何正确的解决库存超卖问题?(建议收藏)》
  • 《Redis五大数据类型与使用场景汇总!!(含完整实战案例,建议收藏)》

好了,今天就到这儿吧,小伙伴们点赞、收藏、评论,一键三连走起呀,我是冰河,我们下期见~~


http://chatgpt.dhexx.cn/article/m2bmG7S2.shtml

相关文章

.Net Core ORM 框架

我的.net core orm 框架 一个简单的orm框架支持的数据库版本新的版本项目地址使用方式实现方式高级特性扩展函数性能bug 一个简单的orm框架 作者在使用很多orm框架的时候觉得查询语句写法似乎不是很好用&#xff0c;例如sqlSugar,EF,sqlSugar呢链接的时候必须注意表的别称&…

SQLAlchemy ORM框架

ORM简介 ORM 全称 Object Relational Mapping, 叫对象关系映射。简单的说&#xff0c;ORM 将数据库中的表与面向对象语言中的类建立了一种对应关系。这样&#xff0c;我们要操作数据库&#xff0c;数据库中的表或者表中的一条记录就可以直接通过操作类或者类实例来完成。 对于…

ORM框架

ORM框架 一、什么是ORM框架 对象关系映射&#xff08;Object Relational Mapping&#xff0c;简称ORM&#xff09;模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术 ORM框架是连接数据库的桥梁&#xff0c;只要提供了持久化类与表的映射关系&#xff0c;OR…

ORM框架使用优缺点

1. 什么是ORM? 对象-关系映射&#xff08;Object-Relational Mapping&#xff0c;简称ORM&#xff09;&#xff0c;面向对象的开发方法是当今企业级应用开发环境中的主流开发方法&#xff0c;关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业…

Redis I/O 多路复用

引出IO多路复用 为什么 Redis 中要使用 I/O 多路复用这种技术呢&#xff1f; 首先&#xff0c;Redis 是跑在单线程中的&#xff0c;所有的操作都是按照顺序线性执行的&#xff0c;但是由于读写操作等待用户输入或输出都是阻塞的&#xff0c;所以 I/O 操作在一般情况下往往不能…

IO多路复用—由Redis的IO多路复用yinch

linux IO多路复用有epoll&#xff0c; poll, select&#xff0c;epoll性能比其他几者要好。 名词比较绕口&#xff0c;理解涵义就好。一个epoll场景&#xff1a;一个酒吧服务员&#xff08;一个线程&#xff09;&#xff0c;前面趴了一群醉汉&#xff0c;突然一个吼一声“倒酒”…

什么是IO多路复用?用来解决什么问题?如何实现?

白话IO多路复用 这里引述知乎大佬对于IO多路复用的机场空管的比喻和理解&#xff1a; 假设你是一个机场的空管&#xff0c; 你需要管理到你机场的所有的航线&#xff0c; 包括进港&#xff0c;出港&#xff0c; 有些航班需要放到停机坪等待&#xff0c;有些航班需要去登机口接…

I/O多路复用

https://blog.csdn.net/baixiaoshi/article/details/48708347 https://blog.csdn.net/z69183787/article/details/52943917 select&#xff0c;poll&#xff0c;epoll都是IO多路复用的机制。所谓I/O多路复用机制&#xff0c;就是说通过一种机制&#xff0c;可以监视多个描述符…

概念 多路复用 到底是个啥?通俗易懂的理解

前言&#xff1a;教育的公平才是最大的公平&#xff0c;本科和专科还是有点差别的。时间长点学方面会充实些。 先给个结论&#xff1a;I/O多路复用技术&#xff08;就是大家经常说的事件循环&#xff09;实际上&#xff0c;事件驱动模型还有另外一个名字&#xff0c;而且更加出…

Redis的IO多路复用原理

什么是阻塞&#xff0c;非阻塞&#xff0c;异步同步&#xff0c;select&#xff0c;poll&#xff0c;epoll&#xff1f;今天我们用一遍文章解开这多年的迷惑。 首先我们想要通过网络接收消息&#xff0c;是这样的一个步骤。 用户空间向内核空间请求网络数据内核空间把网卡数据…

什么是IO多路复用,理解IO多路复用

什么是IO多路复用&#xff1f; IO 多路复用是一种同步IO模型&#xff0c;实现一个线程可以监视多个文件句柄&#xff1b;一旦某个文件句柄就绪&#xff0c;就能够通知应用程序进行相应的读写操作&#xff1b;没有文件句柄就绪就会阻塞应用程序&#xff0c;交出CPU。 多路是指网…

多路复用与多路分用

从现在开始&#xff0c;我们开始传输层的学习&#xff0c;自顶向下第六版中改成了运输层&#xff0c;感觉怪怪的 书中打了邮政服务和代收发信件的兄弟姐妹之间的比方&#xff0c;非常贴切&#xff0c;这是传输层和网络层的作用区别&#xff0c;也就是说&#xff0c;传输层管的是…

多路复用(

apue 多路复用 需求来自用户&#xff0c;用户的需求来自实际的使用场景。在实际运用中&#xff0c;一个系统或者程序需要处理的事件并不是只有一个或一类&#xff0c;而是存在各种各样的事件在一小段事件内一起发生&#xff0c;此时按照没学多线程的逻辑的处理方式就是这样&…

多路复用

讲多路复用先我觉得有必要讲一下什么是阻塞IO、非阻塞IO、同步IO、异步IO这几个东西&#xff1b;linux的五种IO模型&#xff1a; 1)阻塞I/O&#xff08;blocking I/O&#xff09; 2)非阻塞I/O&#xff08;nonblocking I/O&#xff09; 3) I/O复用(select和poll)&#xff08;…

io多路复用的原理和实现_IO多路复用机制详解

select&#xff0c;poll&#xff0c;epoll机制区别总结: 服务器端编程经常需要构造高性能的IO模型&#xff0c;常见的IO模型有四种&#xff1a; (1)同步阻塞IO(Blocking IO)&#xff1a;即传统的IO模型。 (2)同步非阻塞IO(Non-blocking IO)&#xff1a;默认创建的socket都是…

【多路复用器介绍】

【多路复用器介绍】意义 作用 实现 意义逻辑电路原理结构与真值表逻辑电路 实现代码参考资料 意义 多路复用器将接收的复合数据流&#xff0c;依照信道分离数据&#xff0c;并将它们送到对应的输出线上&#xff0c;故称为解多路复用器。 实际生活中&#xff0c;使用多路复用器…

多路复用技术(频分多路复用、时分多路复用和波分多路复用)

基带信号就是将数字信号1或0直接用两种不同的电压来表示&#xff0c;然后送到线路上去传输。 宽带信号则是将基带信号进行调制后形成的频分复用模拟信号。 多路复用技术的基本原理是&#xff1a;各路信号在进入同一个有线的或无线的传输媒质之前&#xff0c;先采用调制技术把…

8、多路复用技术

这一节&#xff0c;我们介绍信道的多路复用&#xff0c;作为数据通信基础的收尾知识点&#xff0c;这个知识点并没有特别复杂的地方&#xff0c;主要是理解不同的复用技术的特点&#xff0c;在一些考试中也没有多少考点&#xff0c;或者说不做重点。 多路复用技术 先从字面上来…

TCP/IP多路复用

所有网络通信的本质目标就是进程间通信。 除了寻址&#xff08;Addressing&#xff09;&#xff0c;IP 协议还有一个非常重要的能力就是路由。 寻址告诉我们去往下一个目的地该朝哪个方向走&#xff0c;路由则是根据下一个目的地选择路径。寻址更像在导航&#xff0c;路由更像…

多路复用,讲的很明白

作者&#xff1a;罗志宇 链接&#xff1a;https://www.zhihu.com/question/32163005/answer/55772739 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 假设你是一个机场的空管&#xff0c; 你需要管理到你机场的所有…