动手改造Ibatis,使其支持文件系统存储数据列 之 看我如何给ResultMap增加属性

本文接上文, http://www.cnblogs.com/suyuan/archive/2009/04/17/1438064.html

这篇文章我要介绍的是给rusultMap的xml段中增加节点,具体效果如下:

image

或许你会问为什么要这样做?

首先我来说说key ,key的作用是指定用于生成hash路径所依赖的对象属性.这里要注意的是你指定的这个属性的值必须是唯一的. 而数据库中的id作为主键必须是唯一值,所以我们一般以 id 来生成我们所需的hash路径.

然后来说明下 datasource ,这里的datasource可以有两个选择 file 或者 db 如果是选择file的话 则对应列根据hash路径存储在文件系统中,如果选择db 则存储在数据库中 ,默认是db 可以省略.

明白了以上添加的节点的作用 ,接下来我们来一步步修改程序使之达到我们的目标:

第一步,修改dtd验证文件:

image   image

这里必须修改 我在上一篇已经介绍过了,这里不再过多解释.请参考上图.

对SqlMap 进行解析是通过com.ibatis.sqlmap.engine.builder.xml.SqlMapParser.java 进行的,这里要说明的是由于我们并没有增加新的node,而是仅仅增加了属性,所以我们仅仅在原有的解析的方法上增加对属性的解析就好了

div css xhtml xml Example Source Code Example Source Code [http://www.cnblogs.com/suyuan/]
parser.addNodelet("/sqlMap/resultMap", new Nodelet() {
      public void process(Node node) throws Exception {
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
        String id = state.applyNamespace(attributes.getProperty("id"));
        String resultClassName = attributes.getProperty("class");
        String extended = state.applyNamespace(attributes.getProperty("extends"));
        String xmlName = attributes.getProperty("xmlName");
        String groupBy = attributes.getProperty("groupBy");
        //解析key
        String key = attributes.getProperty("key");
              
        resultClassName = state.getConfig().getTypeHandlerFactory().resolveAlias(resultClassName);
        Class resultClass;
        try {
          state.getConfig().getErrorContext().setMoreInfo("Check the result class.");
          resultClass = Resources.classForName(resultClassName);
        } catch (Exception e) {
          throw new RuntimeException("Error configuring Result.  Could not set ResultClass.  Cause: " + e, e);
        }
        ResultMapConfig resultConf = state
                                     .getConfig()
                                     .newResultMapConfig(id, resultClass, groupBy, extended, xmlName,key);
        state.setResultConfig(resultConf);
      }
    });
注意代码的最后调用了 newResultMapConfig ,这个也要增加key,像一串,我们只要根据程序一步步跟下去逐步增加key就ok了
 
当我们跟到下面这个地方的时候key必须有一个归宿,他的归宿就是ResultMap对象
请看下图:
image 
 
然后我们跳转到ResultMap类,继续看
image 这里我在ResultMap类中增加了三个属性,key就不用解释了 ,
filehandlerpath其实就是指我一直在说的hash路径.下图展示了生成hash路径的方式.
div css xhtml xml Example Source Code Example Source Code [http://www.cnblogs.com/suyuan/]
 //生成hash路径
  public void setFilehandlerpath(Object key) {
	  if(key!=null)
	  {
		 filehandlerpath = delegate.getBaseDirectory() + this.resultClass.getSimpleName();
		 String hashkey = String.valueOf(key.hashCode());
		 String  split = "/";
		 StringBuilder sb = new StringBuilder();
	     for(int i=0;i<hashkey.length();i=i+2){
	    	if((i+2)<=hashkey.length()){
	    		sb.append(split).append(hashkey.substring(i,i+2));
	    	}
	    	else
	    	{
	    		sb.append(split).append("0"+hashkey.charAt(i));
	    	}	    	
	     }
	     sb.append(split).append(hashkey).append(".data");
		 filehandlerpath +=  String.format("%s", new Object[] { sb.toString() });
	  }
  }
还有一个属性是hasfilestore 用于表示这个map是否有result存储在文件系统中.
以上就是我们增加key这个属性的过程.
下面我们继续讲解在rusult中增加datasource属性
解析的方式和key类似
image 
result在Ibatis中对应的对象是ResultMapping ,所以datasource最终的归宿在ResultMapping对象
我们来看ResultMapping对象 ,这里我增加了三个属性,这三个属性的作用请看注释.
image 
而对这几个属性的利用请参考下面的代码.
div css xhtml xml Example Source Code Example Source Code [http://www.cnblogs.com/suyuan/]
public void addResultMapping(String propertyName, String columnName, Integer columnIndex, Class javaClass, String jdbcType, String nullValue, String notNullColumn, String statementName, String resultMapName, Object impl ,String datasource) {
    errorContext.setObjectId(propertyName + " mapping of the " + resultMap.getId() + " result map");
    TypeHandler handler;
    if (impl != null) {
      if (impl instanceof TypeHandlerCallback) {
        handler = new CustomTypeHandler((TypeHandlerCallback) impl);
      } else if (impl instanceof TypeHandler) {
        handler = (TypeHandler) impl;
      } else {
        throw new RuntimeException("The class '" + impl + "' is not a valid implementation of TypeHandler 
                                   or TypeHandlerCallback");
      }
    } else {
      handler = config.resolveTypeHandler(client.getDelegate().getTypeHandlerFactory(),
                                   resultMap.getResultClass(), propertyName, javaClass, jdbcType, true);
    }
    ResultMapping mapping = new ResultMapping();
    mapping.setPropertyName(propertyName);
    mapping.setColumnName(columnName);
    mapping.setJdbcTypeName(jdbcType);
    mapping.setTypeHandler(handler);
    mapping.setNullValue(nullValue);
    mapping.setNotNullColumn(notNullColumn);
    mapping.setStatementName(statementName);
    mapping.setNestedResultMapName(resultMapName);
    mapping.setDatasource(datasource);
    if(resultMap.getKey()!=null&&resultMap.getKey().equals(propertyName))
    {
    	mapping.setFilehandler(true);
    }
    if (resultMapName != null && resultMapName.length() > 0) {
      resultMap.addNestedResultMappings(mapping);
    }
    mapping.setJavaType(javaClass);
    if (columnIndex != null) {
      mapping.setColumnIndex(columnIndex.intValue());
    } else {
      resultMappingIndex++;
      mapping.setColumnIndex(resultMappingIndex);
    }
    resultMappingList.add(mapping);
    //如果是保存在文件中 则将ResultMap对象中的hasfilestore 置成 true
    if(mapping.isFromfile()){
    	this.sfResultMappingNames.add(mapping.getPropertyName());
    	if(!resultMap.isHasfilestore()){
    		resultMap.setHasfilestore(true);
    	}
    }    
    resultMap.setSfResultMappingNames(sfResultMappingNames);
    resultMap.setResultMappingList(resultMappingList);
  }
 
ok,本章就介绍到这里,不知道你是否看的明白了.没有关系,如果有兴趣就下载一份代码,我们一起来边学边做边讨论吧.
接下来我们将学习image 这个节点的解析和作用.
posted @ 2009-04-24 12:55  雨中漫步的太阳  阅读(2094)  评论(3编辑  收藏  举报