惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
H
Hackread – Cybersecurity News, Data Breaches, AI and More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
小众软件
小众软件
月光博客
月光博客
D
DataBreaches.Net
L
LangChain Blog
美团技术团队
S
SegmentFault 最新的问题
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
博客园 - 司徒正美
aimingoo的专栏
aimingoo的专栏
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
阮一峰的网络日志
阮一峰的网络日志
Y
Y Combinator Blog
I
InfoQ
U
Unit 42
Microsoft Azure Blog
Microsoft Azure Blog
J
Java Code Geeks
博客园 - 三生石上(FineUI控件)
腾讯CDC
Martin Fowler
Martin Fowler

博客园 - 雨中漫步的太阳

基于跨数据库的事务的一个讨论,希望参考下大家的意见 Wave帮助、技巧、术语集 从IBatis2.X 移植到IBatis3.0 sqlMapConfig and sqlMap XML 配置文件升级说明 - 雨中漫步的太阳 .NET正则基础——.NET正则类及方法应用[转载] 按钮单击ThickBox弹出窗口 推荐一款界面设计工具 Balsamiq Mockups jQuery.extend的用法 转载 qq2009 好像和金山词霸屏幕取词有冲突 错误 1 error C2664: 'TextOutW' : cannot convert parameter 4 from 'const char [5]' to 'LPCWSTR' 也发一个有道第二题的算法,练练脑子 使用commons-logging和log4j记录日志[转载] 发一个 Window Live Writer 插件 SyntaxHighlight 代码样式 700万数据随机取10条仅用不到10ms? 动手改造Ibatis,使其支持文件系统存储数据列 之 源码下载编译和SqlMapConfig解析 IBAtisHelper 源代码放出,需要的下载吧 动手改造Ibatis,使其支持文件系统存储数据列 预览 大家讨论下,结合文件系统,给数据库瘦身方案的可行性 Ibatis SelectKey iBatis resultMap groupBy属性使用心得[转载]
动手改造Ibatis,使其支持文件系统存储数据列 之 看我如何给Re...
雨中漫步的太阳 · 2009-04-24 · via 博客园 - 雨中漫步的太阳

本文接上文, 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 这个节点的解析和作用.