借老系统重构我给jpa写了个mybatis风格的查询模块
因为公司老系统是用hibernate3开发的,重构自然过渡到使用Spring Data JPA
。由于系统中对sql
的使用方式还是手动为主,这就造成在service
层存在大量的sql
拼接方式,后续维护比较困难。
因为怀念以往项目对sql
驱动的持久层开发用的mybatis
的时光,笔者参考b站up主Java灭霸詹的手写mybatis系列,为JPA
扩展了一个mybatis
风格的查询模块。
在大佬讲解实现的基础上完成了plugin
模块的编写以支持分页特性,同时扩展了mybatis
的xml文件中的sql
节点标签,让功能按照个人需求实现进一步的定制。
在整个代码实践过程中,笔者对mybatis
的实现原理也有了进一步的认识,同时通过编写这个JPA
的mybatis
风格查询的扩展模块,为后面做sql
的重构也铺平了道路。
封装JDBC
对于JPA
它的优势自然是ORM
框架所具有的对象关系映射,而实际业务中存在大量手写sql
的情况下,用JPA
自然不是最好的选择,如果是公司架构的要求,那对JPA
操作JDBC
的那部分代码做一层封装,让其具有了mybatis
的sql
处理能力,自然会是一件两全其美的事情。
这里封装JPA
的JDBC
操作,只是做了一层sql
映射的逻辑层的节点树结构,在实际执行查询时会执行节点树,通过上下文的串联,将每个sql
节点对应解析出来的sql
进行拼接,得到要执行的目标sql
。并在这个过程中完成sql
中参数占位符的处理,映射参数列表。
而sql
执行所处的环境、数据源连接、事务环境这些都托管给了Spring
管理。最底层只需要调用org.hibernate.Session
的session.doReturningWork()
方法操作jdbc
即可。
xml中编写sql的示例
这里给出笔者实现该模块的示例查询:
这里在实现mybatis
动态查询功能的基础上,做了一些扩展。比如这里的<in>
标签、用于分页查询优化的<sql>
标签。
in查询标签
mybatis
在处理列表形式的参数时使用的<foreach>
标签用起来比较麻烦,笔者在手写mybatis
实现基础功能的基础上扩展了原有标签的功能,实现了简单易用的<in>
标签。执行的效果和mybatis
的<foreach>
标签一样:
分页查询
对于mybatis
提供的plugin
功能,市面上有类似于PageHelper
这样的第三方插件来整合分页功能。笔者翻看其源码,体会到由于mybatis
在封装上的一些安全性考虑,并没有为Plugin
的拦截扩展功能开太多的口子,这就造成插件的第三方开发者需要做很多的设计和实现来适配。
而对于笔者手写mybatis
来说,要扩展插件就变得简单了。框子是笔者定的,为了更好的扩展,可以适当的把口子开大点,让扩展更好的适配。在实现分页拦截器时,笔者为框子底层的类开了类似切面的口子,方便扩展:
这样基于笔者手写的mybatis
,用短短20几行代码就实现了一个功能完备的分页插件:
分页功能的优化
目前市面上的分页插件对于分页的select count
查询,并没有实现对内部sql
的干预机制,更多的是在外面包一层select count(1) from (...) t
,而内层的sql诸如select *
的处理方式并没有屏蔽掉。所以count
查询的效率自然不敢恭维。而笔者在扩展mybatis
手写功能时,对这一块做了用户定制优化:
这里<sql>
标签包裹的内容是在分页列表查询时必要的,而count
查询将会被替换掉,如果指定了countSql
属性,就用属性值代替,否则替换为空。这样无论一个结构多复杂的sql
,用这种包裹和替换方式,都无需为了提高count
查询效率,而单独写一个查询sql
。执行结果正如我们所期望的那样:
原文地址:https://blog.csdn.net/felix_alone2012/article/details/143053230
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!