关于mybatis扩展的一点想法
Posted 程序员A
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于mybatis扩展的一点想法相关的知识,希望对你有一定的参考价值。
本文主要目的是为mybatis的 include 标签添加扩展属性
当使用mybatis进行单表查询时 可以方便的使用 <include> 标签将定义好的<sql> 节点内容包含进来,具体示例如下
<sql id="t_agent_Base_Column_List"> ID, WORKER_ID, <span style="font-family: Arial, Helvetica, sans-serif;">WORKER_NAME, </span> WORKER_MAIN_NUM, WORKER_EXT_NUM, SALE_PHONE, IS_PART_TIME, LAST_LOGIN_TIME, SIGN, HEAD_PIC,WEI_XIN, WX_EWM, WEIBO, PRACTIC_CERT, WORK_YEAR, SERVICE_JSON, SERVICE_AREA, PRAISE_COUNT, SHOP_VIEW_COUNT, CITY_CODE, AREA_CODE, AREA_NAME, PLACE_CODE, PLACE_NAME, SORT_SCORE, VOCAT_SKILL, FEATURES, LEAD_REPUTABLY, STATUS, VERSION, INSERT_TIME, UPDATE_TIME, BUSINESS_TYPE, MANIFESTO, BACKGROUND_IMAGE, TITLE_ID </sql> <!-- 根据主键查询 --> <select id="selectById" resultMap="AgentInfo" parameterType="java.lang.Integer"> SELECT <include refid="t_agent_Base_Column_List" /> FROM AGENT_INFO WHERE ID = #{id,jdbcType=INTEGER} </select>
SELECT A.ID, A.WORKER_ID, A.WORKER_NAME,.....经纪人表的其他字段 B. LEVEL, --经纪人等级 B.SUBJECTS_NUM, --完成科目数 B.LOOK_NUM, --带看数 B.DEAL_NUM --成交数 <span style="white-space:pre"> </span>FROM AGENT_INFO A LEFT JOIN AGENT_TITLE_INFO B ON A.TITLE_ID=B.ID WHERE A.ID = #{ID}
<!--AgentInfo 中是所有经纪人表字段 --> <resultMap id="agentExendMap" type="com.kevin.learning.modules.entity.agent.AgentInfoExtend" extends="AgentInfo"> <result column="LEVEL" property="level" jdbcType="VARCHAR"/> <result column="SUBJECTS_NUM" property="subjectsNum" jdbcType="VARCHAR"/> <result column="LOOK_NUM" property="lookNum" jdbcType="VARCHAR"/> <result column="DEAL_NUM" property="dealNum" jdbcType="VARCHAR"/> </resultMap>
我们可以看到上面的 sql 语句并不能复用定义好的t_agent_Base_Column_List 这个节点来引用整个T_AGENT字段,而是重新写了一遍,而且 经纪人详情表也没有复用。
下面来看一下我的一个扩展方案 ,因为我们的sql是要查询 经纪人信息,还有经纪人详情的几个字段 ,分别是 AGEN_INFO 表和 AGENT_TITLE_INFO表,看一下做了扩展的配置文件,其实这也是整篇文章唯一想要实现的效果
<select id="selectExtendList" resultMap="agentExendMap" parameterType="map"> select <include refid="t_agent_Base_Column_List" prefix="A."/>, <include refid="com.kevin.learning.modules.dao.agenttitle.IAgentTitleInfoDAO.t_agent_info_title_Base_Column_List" prefix="B." excludeCols="UPDATE_TIME,INSERT_TIME,STATUS,DESCRIPTION,ID"/> FROM AGENT_INFO A LEFT JOIN AGENT_TITLE_INFO B ON A.TITLE_ID=B.ID WHERE A.ID = #{ID} </select>注:另一个 include标签是另一个mapper文件定义的,mybatis支持 引用其他文件的 sql节点
主要做了扩展的地方有两个
1、为 <include>节点添加了 prefix属性,这样在引用这个节点的字段都会加上这个前缀
2、为<include>节点添加 excludeCols属性,mybatis其实是可以引用另一个mapper文件中定义的sql节点的,我们上面引用了经纪人详情表的 base_column_List(包含了该表的所有字段),这个属性中定义的字段是会被排除的,以逗号分隔
结果:我们的 sql 包含的字段是 agent_info表的全部字段 + ( AGENT_TITLE_INFO 表全部字段 - excludeCols中定义的字段 )
level 和 lookNum 是 经纪人详情中的字段,这样就查出来了,同时被排除的 insert_time和update_time就没有查询
实现方法分析
这个改动主要是对源码码的修改是很少的,就只在myabtis启动加载 解析mapper文件时将自己需要的特性添加进去 , 要修改的类是 XMLIncludeTransformer 的 applyInclude方法
mybatis在解析sql时将 include 解析完成 会替换掉 原来的 include 节点
代码的处理部分很简单,就是将 sql节点中的 sql语句加上 prefix,然后将整个 字符串 设置到 DOM节点中 ,这样扩展就完成了, 对了,还有一个地方要改,那就是要对 mybatis的DTD文件做一个小改动,因为启动时会用DTD对mapper的xml进行验证
以上是关于关于mybatis扩展的一点想法的主要内容,如果未能解决你的问题,请参考以下文章