mybatis的继承extend和导入import

本文作废作废。
原因:跨xml引用: use in another mapper, you just need to specify the fully-qualified id.
本文的唯一一点好处可以省去写namespace的麻烦。

1. 问题

在工作中和同事共同开发一个模块,底层的数据模型用到的是同一个表。日常开发常规地都会动到这个数据模型实体的mapper。合并代码的时候肯定会有冲突相互覆盖。后来想各自写mapper.xml处理相关的逻辑,但是这样resultMap就会有多份。需求经常变,到时候多份resultMap维护起来也麻烦。

所以想到可以扩展一下mybatis支持xml继承。后来查找了一下发现mybatis的resultMap支持继承,利用extends属性扩展原有的定义。最后决定在也在mapper元素上增加extends属性保存要继承的mapper.xml文件。可以把公共的配置提取出来,把复杂的业务逻辑sql和基础的curd sql写在不同的文件里。

后来有另外加入import功能,<import src="xx.xx.xx">导入其他文件的配置,原理也和extends差不多。类比 类的继承和组合。

2. mybatis改动的地方

2.1 mybatis-3-mapper.dtd

需要改动org.apache.ibatis.builder.xml包下的mybatis-3-mapper.dtd,给mapper增加extends属性

<!ELEMENT mapper (cache-ref | cache | import* | resultMap* | parameterMap* | sql* | insert* | update* | delete* | select* )+>
<!ATTLIST mapper
xmlns:fo CDATA #IMPLIED
namespace CDATA #IMPLIED
extends CDATA #IMPLIED
>  
    
<!ELEMENT import EMPTY>
<!ATTLIST import
src CDATA #REQUIRED
>
2.2 XMLMapperBuilder.configurationElement

需要改动XMLMapperBuilder.configurationElement解析映射xml的处理过程:增加extends属性的处理,具体代码。没有做循环依赖处理:

private void configurationElement(XNode context) {
    try {
      //1.配置namespace
      String namespace = context.getStringAttribute("namespace");
      if (namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      builderAssistant.setCurrentNamespace(namespace);
      
      extendsElement(context);
      mapperChildElement(context);
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
    }
  }
  
  /**根据mapper上的extends所指向的xml文件,加载xml的配置
   * 增加父extends,继承xml里mapper下的所有元素*/
  private void extendsElement(XNode context) throws Exception
  {
	  String extend = context.getStringAttribute("extends");
	  if(extend==null)
		  return;
	  String[] xmlResources=extend.replace('.', '/').split(",");
	  for(String xmlResource:xmlResources){
	            fileElements(xmlResource);
	  }		  
      }
	  
  private void importElement(List<XNode> list) throws Exception
  {
          for(XNode node:list)
          {
               String src = node.getStringAttribute("src");
               if(src==null)
                   return;
              String[] xmlResources=src.replace('.', '/').split(",");
              for(String xmlResource:xmlResources)
                 fileElements(xmlResource);
           }
   }

      private void fileElements(String xmlResource) throws Exception
      {
          xmlResource = xmlResource+ ".xml";
          InputStream inputStream = Resources.getResourceAsStream(Thread.currentThread().getContextClassLoader(),xmlResource);
          XPathParser xpathParser=new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver());
          XNode extendsContext=xpathParser.evalNode("/mapper");
          extendsElement(extendsContext);
          mapperChildElement(extendsContext);
      }
  
  private void mapperChildElement(XNode context) throws Exception
  {
      //1.import
      importElement(context.evalNodes("/mapper/import"));
      //2.配置cache-ref
      cacheRefElement(context.evalNode("cache-ref"));
      //3.配置cache
      cacheElement(context.evalNode("cache"));
      //4.配置parameterMap(已经废弃,老式风格的参数映射)
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      //5.配置resultMap(高级功能)
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      //6.配置sql(定义可重用的 SQL 代码段)
      sqlElement(context.evalNodes("/mapper/sql"));
      //7.配置select|insert|update|delete TODO
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
  }

3. 使用

1)普通的HelloWordMapper.xml映射文件,在mapper元素上加extends继承cn.alpha.demo.BaseMapper

<mapper namespace="cn.alpha.demo.persistence.HelloWorldMapper" extends="cn.alpha.demo.BaseMapper">		
	<select id="getData" resultMap="ActivRePropMap" flushCache="false">
		select NAME_,VALUE_,REV_ from act_ge_property
	</select>
</mapper>

2)BaseMapper.xml父映射文件, 在mapper元素上加extends继承cn.alpha.demo.BaseMapper2

<mapper namespace="cn.alpha.BaseMapper" extends="cn.alpha.demo.BaseMapper2">		
	<resultMap id="ActivRePropMap" type="cn.alpha.demo.bo.ActivReProp" extends="ActivRePropMap-base">
		<result property="rev"  column="REV_"/>
	</resultMap>		
</mapper>

3)BaseMapper2.xml祖先映射文件

<mapper namespace="cn.alpha.BaseMapper2" >		
	<resultMap id="ActivRePropMap-base" type="cn.alpha.demo.bo.ActivReProp">
		<id property="name" column="NAME_" />
		<result property="value"  column="VALUE_"/>
	</resultMap>		
</mapper>

转载于:https://my.oschina.net/braveCS/blog/771538

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值