学习笔记 之 IContainerFactory

从我当前学习来看,IContainerFactory 主要定义Model和Record类对象中, 存储数据映射字段键值的数据类型。本次笔记记录下相关代码。提供的默认实现和三个实现类,如下:

1、默认为HashMap,

static final IContainerFactory defaultContainerFactory = new IContainerFactory() {
    public Map<String, Object> getAttrsMap() {
        return new HashMap<String, Object>();
    }

    public Map<String, Object> getColumnsMap() {
        return new HashMap<String, Object>();
    }
}

2、OrderedFieldContainerFactory,使用LinkedHashMap,达到查询返回字段和select语句中字段顺序一致。

public Map<String, Object> getAttrsMap() {
    return new LinkedHashMap();
}

public Map<String, Object> getColumnsMap() {
    return new LinkedHashMap();
}

3、DaoContainerFactory,自定义了DaoMap,在所有get和put等操作数据的方法中,都抛出了异常,达到某一Model和Record只读的效果。

public static final Map<String, Object> daoMap = new DaoMap<Object>();
public static final Set<String> daoSet = new DaoSet();

private DaoContainerFactory() {
}

public Map<String, Object> getAttrsMap() {
    return daoMap;
}

public Map<String, Object> getColumnsMap() {
    return daoMap;
}

public static class DaoMap<V> implements Map<String, V> {

    public V put(String key, V value) {
       throw new RuntimeException("dao 只允许调用查询方法");
    }

    public V get(Object key) {
       throw new RuntimeException("dao 只允许调用查询方法");
    }
}

需要注意的是,DaoContainerFactory不支持被外部调用,仅用于Model的dao()方法

public M dao() {
    attrs = DaoContainerFactory.daoMap;
    modifyFlag = DaoContainerFactory.daoSet;
    return (M)this;
}

4、CaseInsensitiveContainerFactory 中的 CaseInsensitiveMap 实现的TreeMap,在对Model对象进行add时,通过convertCase方法对key进行大小写转换,达到key统一大小写的效果。

public CaseInsensitiveContainerFactory() {
}

public CaseInsensitiveContainerFactory(boolean toLowerCase) {
    this.toLowerCase = toLowerCase;
}

public Map<String, Object> getAttrsMap() {
    return new CaseInsensitiveMap<Object>();
}

public Map<String, Object> getColumnsMap() {
    return new CaseInsensitiveMap<Object>();
}

private String convertCase(String key) {
    if (toLowerCase != null) {
       return toLowerCase ? key.toLowerCase() : key.toUpperCase();
    } else {
       return key;
    }
}


类方法实现源码如上述,具体运用如:

我们在JFinalConfig的插件配置模块配置 ActiveRecordPlugin 时 setContainerFactory方法即可

public void configPlugin(Plugins me) {
    DruidPlugin druidPlugin = ... 
    ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
    // arp.setContainerFactory(new CaseInsensitiveContainerFactory());
    // arp.setContainerFactory(new OrderedFieldContainerFactory());
}


具体作用的过程是这样的

1、Model对象创建时候,申明了attrs

private Map<String, Object> attrs = createAttrsMap();   

private Map<String, Object> createAttrsMap() {
    Config config = _getConfig();
    if (config == null) {
       return DbKit.brokenConfig.containerFactory.getAttrsMap();
    }
    return config.containerFactory.getAttrsMap();
}

2、写入的时候就是  

attrs.put(key, value)

3、查询时候,主要体现在ModelBuild的实现类

Model<?> ar = modelClass.newInstance();
Map<String, Object> attrs = CPI.getAttrs(ar);
for (int i=1; i<=columnCount; i++) {
    Object value;
    int t = types[i];
    if (t < Types.DATE) {
       if (t == Types.TINYINT) {
          value = BuilderKit.getByte(rs, i);
       } else if (t == Types.SMALLINT) {
          value = BuilderKit.getShort(rs, i);
       } else {
          value = rs.getObject(i);
       }
    } else {
       if (t == Types.TIMESTAMP) {
          value = rs.getTimestamp(i);
       } else if (t == Types.DATE) {
          value = rs.getDate(i);
       } else if (t == Types.CLOB) {
          value = handleClob(rs.getClob(i));
       } else if (t == Types.NCLOB) {
          value = handleClob(rs.getNClob(i));
       } else if (t == Types.BLOB) {
          value = handleBlob(rs.getBlob(i));
       } else {
          value = rs.getObject(i);
       }
    }
    
    attrs.put(labelNames[i], value);


评论区

热门分享

扫码入社