重复造轮子(4) — 手写orm框架Ibernate(下)

简介: 重复造轮子(4) — 手写orm框架Ibernate(下)

3. Core核心包内容


通过一个对象,配置好相应的注解之后,如何去通过扫描识别属性,然后再自动生成sql返回对象,这个才是整个框架的核心之处。Ibernate里面涉及了一个叫做ISessionUtil的接口。它的具体实现类是org.lh.ibernate.core.impl.SessionUtil类。


首先构建SessionUtil对象的构造函数


网络异常,图片无法展示
|


至于这里面的构造参数为什么要有一个class对象,这个后边再说。


sessionUtil里面有很多有简单的函数:保存,更新,删除


网络异常,图片无法展示
|


例如说插入的实现方式主要在org.lh.ibernate.core.impl.InsertUtil


类里面进行。


主要的思路就是,通过反射获取数据表名的字段名字,然后通过相应传入对象的字段属性来进行赋值,动态创建sql语句进行插入即可。


网络异常,图片无法展示
|


为了防止sql注入,所以这里面的思路是找出需要插入的字段数量,创建足够多的占位符?,并且每个占位符映射的字段和实体类的字段顺序一致。


这个插入的实现还是比较简单的,稍微说一下里面的两个自定义函数吧:


getAttrFromFieldHasColumnAnnotation,它的功能是获取所有含有@column注解的字段的属性值,原理主要是采用反射的方式:具体实现在org.lh.ibernate.core.impl.FieldHandle里面


网络异常,图片无法展示
|


然后就是DbUtil里面的一个executeUpdate自定义函数,通过传入相应的sql语句,然后再去给sql里面的占位符赋值。但是有个前提,就是每个占位符对应的值要一一匹配好。

关于插入的功能基本也就这样了,如果读者能耐心地把这些看透,并且实现的话,可能还会发现很多有趣的部分。


同理,删除对象和更新对象的原理也基本是这样。这里就不一一介绍了。


查询操作:


查询操作比较另类,因为它需要和结果集进行动态映射,个人觉得比读操作要困难些。例如说查询操作:


网络异常,图片无法展示
|


这段代码的含义就是,当某个类如果标注了相应的缓存注解,就会先从缓存redis里面去查找,反之就是会从mysql里面查找。


关于缓存查找这个主要是用了jedis的api来进行搜索,具体代码在org.lh.ibernate.cache里面有,如果有部分api看不懂的话,百度上边找找大概就能搜索到了。


我们继续看核心部分:


网络异常,图片无法展示
|


如何能够生成sql语句,这个有了前边的插入,删除,更新经验之后,应该很快就能想到。但是如何才能动态化将ResultSet转换为相应的具体对象,这是一个难点。


慢慢来,经过思考之后,我设计了一个QueryUtil类,里面专门存放对于查询代码的封装方法,findOneObjBySql就是其中之一。


网络异常,图片无法展示
|


是的,你会发现这里面的前期部分就是动态生成sql语句,这个比较简单,后边用到了一个Dbutil的query方法,这个类在整个框架里面是进常会被用到的,而且非常核心。


网络异常,图片无法展示
|


这段源码只需要稍微了解一些jdbc基本都能读懂。


好了,返回了相应的ResultSet之后,就可以动态化的设置转换了。


这里面的ResultSetHandler实现原理可能有些复杂,需要比较耐心地去看下去才可以:


网络异常,图片无法展示
|


这里面出现了一个我在google上查到的jdk函数,叫做属性修改器PropertyDescriptor,是的,这已经是比较偏向于底层的东西了,如果你有耐心去研究下去的话,你的java能力一定会大涨的。


使用属性修改器,动态修改某个属性的值,然后再通过Method里面的invoke代理进行相应类的属性更新,这样就能创建一个新的对象了。


关于多个对象的结果集转换为List类型的函数,大概思路和上边的类似,这里就不多讲了




关于用户的自定义sql查询的底层原理又是如何的呢?


自定义sql查询方法的具体使用方式如下所示:


网络异常,图片无法展示
|


先创建一个ParameterLink对象,然后需要用这个对象add相应的占位符参数,需要一一匹配好,然后才能传入参数。


原理其实很简单,就是Dbutil里面的query方法。


关于Dbutil里面的query方法而言,里面包含有一个ParameterLink对象,这个对象的位置在org.lh.ibernate.core.tools里面,这个类主要是采用了一种链式编程的思想,有点像设计模式里面的责任链模式,所以在添加参数的时候会处理的比较灵活。这里需要注意一下,ParameterLink里面添加的内容需要和条件字段一一匹配。


关于ParameterLink的截图:


网络异常,图片无法展示
|


4.自定义接口创建Dao的具体实现


在Ibernate的1.3版本当中,最主要是添加了invoker这个包


网络异常,图片无法展示
|


这里面的到设计有点借鉴了mybatis和springdata的思想,通过开发者定义接口,然后在实际生产环境中动态化的生成实例类,从而完成相应的crud操作。


网络异常,图片无法展示
|


在IbernateBaseDao里面,有多个已经预定义好的crud函数,由于最近事情有点多,还有些许功能未有添加,希望各位开发者谅解。


网络异常,图片无法展示
|


开发中遇到的困难:


如何动态化地在jvm中通过接口来创建类实例;


使用asm字节码框架来获取某个函数参数名称;


如何更加高效和有用地封装繁琐的函数和类….


如果你对于我的源码表示看不懂,没关系,只要在看完之后,对框架有了更深的认识,小编我也就知足了。


可能各位读者会疑惑,为什么


如果对于源码有兴趣的朋友,可以到我的gitee上边去下载:

gitee.com/IdeaHome_ad…


目录
相关文章
|
SQL XML 前端开发
比mybatis还好的ORM,有点GraphQL语法的味道
个新的类似ORM的框架,具备了ORM框架的功能,同时也还有一点 GraphQL语法的味道,这个新的框架叫Bean Searcher
352 0
|
2月前
|
XML 缓存 Java
手写Spring源码(简化版)
Spring包下的类、手写@ComponentScan注解、@Component注解、@Autowired注解、@Scope注解、手写BeanDefinition、BeanNameAware、InitializingBean、BeanPostProcessor 、手写AnnotationConfigApplicationContext
手写Spring源码(简化版)
|
设计模式 Java Spring
用300行代码手写1个Spring框架,麻雀虽小五脏俱全
为了解析方便,我们用application.properties来代替application.xml文件,具体配置内容如下:
46 0
|
SQL XML JavaScript
MyBatis的10种精妙用法,真是妙啊!
MyBatis的10种精妙用法,真是妙啊!
|
Java 数据库连接 数据库
返璞归真,学了那么多技术栈,那些 [Mybatis-plus] 之 CRUD操作你还熟悉吗
返璞归真,学了那么多技术栈,那些 [Mybatis-plus] 之 CRUD操作你还熟悉吗
83 0
|
SQL 设计模式 XML
面试官:MyBatis 插件有什么用途?说说底层原理?我竟然不会。。
面试官:MyBatis 插件有什么用途?说说底层原理?我竟然不会。。
402 0
面试官:MyBatis 插件有什么用途?说说底层原理?我竟然不会。。
|
设计模式 SQL 存储
【MyBatis】面试官:MyBatis中是如何使用设计模式的?
本篇文章了解一下MyBatis中运用到的设计模式,我们在实际的开发中很大程度上只是对设计模式留在一个理论的环节上,缺少实践,通过源码,我们可以学习一下这些设计模式的实践方式,有利于我们能够更深入的理解和使用设计模式。
|
消息中间件 编解码 Dubbo
第02篇:手写JavaRPC框架之设计思路
本篇文章的主要内容就是设计我们自己的通信协议及架构,可以这样说如果没有了本篇文章的内容,就不可能实现RPC。因为RPC的最基本要求就是能实现远程通信。本篇文章是讲述通信层的设计思路,
241 0
第02篇:手写JavaRPC框架之设计思路
|
网络协议 Dubbo Java
第01篇:手写JavaRPC框架之思路分析
本系列文章的总体目标是从零实现一个RPC框架,我们将从TCP通信协议开始, 一步一步实操,将socket 二进制数据流一步一步变成Java可以认识的数据类型, 从而最终实现RPC远程通信,并可以集成在Spring中,同时也可以支持SpringBoot的自动化配置。最终我们会将项目发布到全球Maven仓库, 让大家都可以下载学习。
136 0
第01篇:手写JavaRPC框架之思路分析
|
SQL 缓存 Oracle
重复造轮子(4) — 手写orm框架Ibernate(上)
重复造轮子(4) — 手写orm框架Ibernate(上)
116 0