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上边去下载: