大家好,我是冰河~~

最近很多小伙伴对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五大数据类型与使用场景汇总!!(含完整实战案例,建议收藏)》

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

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

  1. 10分钟手撸极简版ORM框架!

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

  2. 如何手撸一个较为完整的RPC框架

    [文章作者/来源]一个没有追求的技术人/https://sourl.cn/sJ4Brp 缘 起 最近在公司分享了手撸RPC,因此做一个总结. 概 念 篇 RPC 是什么? RPC 称远程过程调用(Re ...

  3. 如何手撸一个较为完整的RPC框架?

    点击关注公众号,实用技术文章及时了解 来源:juejin.cn/post/6992867064952127524 缘起 最近在公司分享了手撸RPC,因此做一个总结. 概念篇 RPC 是什么? RPC ...

  4. CherryPy: 一个极简主义Python Web框架

    目录 1 前言 2 SWGI(Web Server Gateway Interface) 3 特色与优势 4 Hello, World! 5 不同URL调用不同函数 6 带有参数的URL 7 处理表单 ...

  5. Spring Boot(5)一个极简且完整的后台框架

    一个完整的极简后台框架,方便做小项目的时候可以快速开发. 这里面多贴图片和代码,做个参考吧,代码可以下载下来自己看看,里面这套后台模板不错,喜欢的拿去. 先放几张图 项目介绍 SpringBoot,我 ...

  6. JAVA程序员的堕落:只知框架不懂底层原理

    我曾在多个场合撰文说过,现在培训出来的企业Java开发兵团只知道使用某种框架,但完全不知道这些框架的底层原理.今天早上,在依次对三个职位的应聘者面试中,我又再次见到了这种情形. 我们的顾问公司收到了一 ...

  7. Spring Boot 一个极简且完整的后台框架

    一个完整的极简后台框架,方便做小项目的时候可以快速开发. 这里面多贴图片和代码,做个参考吧,代码可以下载下来自己看看,里面这套后台模板不错,喜欢的拿去. 先放几张图 image image image ...

  8. 在用安全框架前,我想先让你手撸一个登陆认证

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 转自:RudeCrab, 链接:blog.csdn.net ...

  9. 极简微前端框架-京东MicroApp开源了

    前言 MicroApp是一款基于类WebComponent进行渲染的微前端框架,不同于目前流行的开源框架,它从组件化的思维实现微前端,旨在降低上手难度.提升工作效率.它是目前市面上接入微前端成本最低的 ...

最新文章

  1. faster rcnn论文_faster-rcnn论文思路及代码编译
  2. Django Book 2.0 笔记——会话、用户和注册
  3. 技术人员如何创业《四》- 打造超强执行力团队(转载)
  4. java商城_基于Java,jfinal web框架开发出微信商城,微信分销商城源码分享
  5. matlab向量归一化_已知近似的特征值,求特征向量
  6. Windows EC2 Instance 忘记密码如何重置
  7. 开源天生就不是为了赚钱!
  8. 牵手高通的百度是要拿科大讯飞开刀了?
  9. UVA489 Hangman Judge【模拟】
  10. 个人的一些MySql管理经验
  11. AJAX实现导航式多条件搜索
  12. Docker网络详解
  13. Android联网的权限
  14. 三调 图斑地类面积_图斑地类面积理论值计算方法说明 -
  15. 架构师应该知道的37件事
  16. JS求 一张纸厚度是0.07毫米,假设这张纸可以限次对折,问对折几次可以超过珠峰?8848米
  17. 域名被微信/QQ红了(被封锁、被屏蔽、被和谐)后最好的解决方法
  18. iOS调试_Couldn't load project
  19. JimuReport积木报表打印多出一页空白页问题(解决方案)
  20. 为高效学习神器 Anki 部署一个专属同步服务器

热门文章

  1. 语言及框架演变系列文章:J2EE简介
  2. 如何去除从windows上传到unix的前导符^M
  3. CXF 发布WS 1 counts of IllegalAnnotationExceptions 问题
  4. 为什么老实人总是节节败退(关于婚姻)
  5. python image库安装_Python如何安装Image库呢?
  6. 【Python3】数组去重和排序
  7. 收藏 不显示删除回复显示所有回复显示星级回复显示得分回复 经典的60句话,慢慢体会 ^_^[
  8. linux怎么安装useradd命令,Linux下useradd命令
  9. matlab 除去振动,Matlab讨论区 - 声振论坛 - 振动,动力学,声学,信号处理,故障诊断 - Powered by Discuz!...
  10. OpenStack安装Glance组件