重复造轮子(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…


目录
相关文章
|
Kubernetes 安全 Devops
【云效流水线 Flow 测评】驾驭云海:五大场景下的云效Flow实战部署评测
云效是一款企业级持续集成和持续交付工具,提供免费、高可用的服务,集成阿里云多种服务,支持蓝绿、分批、金丝雀等发布策略。其亮点包括快速定位问题、节省维护成本、丰富的企业级特性及与团队协作的契合。基础版和高级版分别针对小型企业和大规模团队,提供不同功能和服务。此外,云效对比Jenkins在集成阿里云服务和易用性上有优势。通过实战演示了云效在ECS和K8s上的快速部署流程,以及代码质量检测和AI智能排查功能,展示了其在DevOps流程中的高效和便捷,适合不同规模的企业使用。本文撰写用时5小时,请各位看官帮忙多多支持,如有建议也请一并给出,您的建议能帮助我下一篇更加出色。
219110 19
|
设计模式 Java API
重构旧代码的秘诀:用设计模式 - 适配器模式(Adapter)给Java项目带来新生
【4月更文挑战第7天】适配器模式是解决接口不兼容问题的结构型设计模式,通过引入适配器类实现目标接口并持有不兼容类引用,实现旧代码与新接口的协作。适用于处理兼容性问题、整合遗留代码和集成第三方库。应用时,识别不兼容接口,创建适配器类转换方法调用,然后替换原有引用。注意保持适配器简单、使用组合和考虑扩展性。过度使用可能导致系统复杂和维护成本增加,应谨慎使用。
321 4
|
存储 消息中间件 缓存
Redis 简介
10月更文挑战第14天
322 58
|
9月前
|
人工智能 自然语言处理 搜索推荐
《AI领航元宇宙:解锁跨平台体验新密码》
元宇宙正从科幻走向现实,整合多种新技术,承载未来社交、娱乐、工作的愿景。AI在实现跨平台无缝体验中扮演核心角色,打破技术壁垒,助力底层兼容,通过语义理解和中间件实现多设备互通。AI生成内容确保一致性体验,实时适配优化交互流畅度,并提供个性化推荐和智能客服支持,提升用户体验。尽管面临数据隐私等挑战,AI将持续创新,推动元宇宙的全面发展,开启数字生活新篇章。
246 5
|
Java API
List转Map(id为key,list为value)
List转Map(id为key,list为value)
1069 0
|
存储 缓存 负载均衡
一文搞懂一致性hash的原理和实现
一文搞懂一致性hash的原理和实现
|
设计模式 人工智能 前端开发
七大设计原则之开闭原则应用
七大设计原则之开闭原则应用
281 0
|
存储 canal 消息中间件
数据仓库系列(三)数仓分层的意义价值及如何设计数据分层
数据仓库系列(三)数仓分层的意义价值及如何设计数据分层
1916 0
数据仓库系列(三)数仓分层的意义价值及如何设计数据分层
|
数据采集 人工智能 供应链
2024,需要一场“增量革命”
2024,需要一场“增量革命”
199 0
|
机器学习/深度学习 安全 数据安全/隐私保护
Windows系统安装Jupyter Notebook并实现公网访问内网笔记服务
Windows系统安装Jupyter Notebook并实现公网访问内网笔记服务
386 0