`

关于mongodb存储HashMap字段的问题

阅读更多

    昨天晚上碰到了一个问题,弄了老半天后来在别人的帮助下发现是mongodb存储HashMap类型字段时的问题,直接看代码吧:

//这是实体类中的那个HashMap类型的字段
private HashMap<String, String> properties;
public HashMap<String, String> getProperties() {
	return properties;
}
public void setProperties(HashMap<String, String> properties) {
	this.properties = properties;
}

   这是monog保存实体时报的错误:

    可以看出是数据库操作时出现的异常,再查看报错那地方的源码如下:

 

 

/**
     * If the given class format is not already present in the given map and
     * a format for this class name does not already exist, creates an
     * uninitialized format, adds it to the map, and also collects related
     * formats in the map.
     */
    public Format createFormat(Class type, Map<String, Format> newFormats) {
       
        ......
        /*
         * Although metadata is only needed for a complex type, call
         * getClassMetadata for all types to support checks for illegal
         * metadata on other types.
         */
      //此处获取的metadata为NULL,基本上就可以得出应该是由于类型不匹配所导致的问题了
        ClassMetadata metadata = model.getClassMetadata(className);
        /* Create format of the appropriate type. */
        String proxyClassName = null;
        if (proxyClassMap != null) {
            proxyClassName = proxyClassMap.get(className);
        }
        if (proxyClassName != null) {
            format = new ProxiedFormat(this, type, proxyClassName);
        } else if (type.isArray()) {
            format = type.getComponentType().isPrimitive() ?
                (new PrimitiveArrayFormat(this, type)) :
                (new ObjectArrayFormat(this, type));
        } else if (type.isEnum()) {
            format = new EnumFormat(this, type);
        } else if (type.getEnclosingClass() != null && 
                   type.getEnclosingClass().isEnum()) {

            /* 
             * If the type is an anonymous class of an enum class, the format
             * which represents the enum class will be created. [#18357]
             */
            format = new EnumFormat(this, type.getEnclosingClass());
        } else if (type == Object.class || type.isInterface()) {
            format = new NonPersistentFormat(this, type);
        } else {
            if (metadata == null) {
         //此处为第799行报错的地方,所以应该是metadata的问题,再往上追踪metadata的出处
                throw new IllegalArgumentException
                    ("Class could not be loaded or is not persistent: " +
                     className);
            }
            if (metadata.getCompositeKeyFields() != null &&
                (metadata.getPrimaryKey() != null ||
                 metadata.getSecondaryKeys() != null)) {
                throw new IllegalArgumentException
                    ("A composite key class may not have primary or" +
                     " secondary key fields: " + type.getName());
            }

            /*
             * Check for inner class before default constructor, to give a
             * specific error message for each.
             */
            if (type.getEnclosingClass() != null &&
                !Modifier.isStatic(type.getModifiers())) {
                throw new IllegalArgumentException
                    ("Inner classes not allowed: " + type.getName());
            }
            try {
                type.getDeclaredConstructor();
            } catch (NoSuchMethodException e) {
                throw new IllegalArgumentException
                    ("No default constructor: " + type.getName(), e);
            }
            if (metadata.getCompositeKeyFields() != null) {
                format = new CompositeKeyFormat
                    (this, type, metadata,
                     metadata.getCompositeKeyFields());
            } else {
                EntityMetadata entityMetadata =
                    model.getEntityMetadata(className);
                format =
                    new ComplexFormat(this, type, metadata, entityMetadata);
            }
        }
        /* Collect new format along with any related new formats. */
        newFormats.put(className, format);
        format.collectRelatedFormats(this, newFormats);

        return format;
    }

 
    由于报错显示了BasicDbobject, 那我们再来看一下BasicDbobject的源码:

/*
 * Copyright (c) 2008-2014 MongoDB, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BasicDBObject.java

package com.mongodb;

import com.mongodb.util.JSON;
import org.bson.BasicBSONObject;

import java.util.Map;

/**
 * a basic implementation of bson object that is mongo specific.
 * A <code>DBObject</code> can be created as follows, using this class:
 * <blockquote><pre>
 * DBObject obj = new BasicDBObject();
 * obj.put( "foo", "bar" );
 * </pre></blockquote>
 */
public class BasicDBObject extends BasicBSONObject implements DBObject {

    private static final long serialVersionUID = -4415279469780082174L;
    
    /**
     *  Creates an empty object.
     */
    public BasicDBObject(){
    }
    
    /**
     * creates an empty object
     * @param size an estimate of number of fields that will be inserted
     */
    public BasicDBObject(int size){
    	super(size);
    }

    /**
     * creates an object with the given key/value
     * @param key  key under which to store
     * @param value value to stor
     */
    public BasicDBObject(String key, Object value){
        super(key, value);
    }

    /**
     * Creates an object from a map.
     * @param m map to convert
     */
    //由于实体中只有一个hashmap字段比较特殊,所以怀疑此处的Map可能有问题
    public BasicDBObject(Map m) {
        super(m);
    }

    public boolean isPartialObject(){
        return _isPartialObject;
    }

    public void markAsPartialObject(){
        _isPartialObject = true;
    }

    /**
     * Returns a JSON serialization of this object
     * @return JSON serialization
     */    
    @Override
    public String toString(){
        return JSON.serialize( this );
    }

    @Override
    public BasicDBObject append( String key , Object val ){
        put( key , val );
        return this;
    }

    public Object copy() {
        // copy field values into new object
        BasicDBObject newobj = new BasicDBObject(this.toMap());
        // need to clone the sub obj
        for (String field : keySet()) {
            Object val = get(field);
            if (val instanceof BasicDBObject) {
                newobj.put(field, ((BasicDBObject)val).copy());
            } else if (val instanceof BasicDBList) {
                newobj.put(field, ((BasicDBList)val).copy());
            }
        }
        return newobj;
    }
    
    private boolean _isPartialObject;
} 

 

//再打开BasicDBObject的父类,发现BasicBSONObject继承了java.util.LinkedHashMap
//所以猜测可能是Bdb里面的vo不识别非JDK自身的HashMap实现
public class BasicBSONObject extends LinkedHashMap<String,Object> 
implements BSONObject {

}

   

    解决方案:

//修改set方法
public void setProperties(HashMap<String, String> properties) {
	HashMap<String, String> map = new HashMap<String, String>();
	map.putAll(properties);
	this.properties = map;
}

 

 

    关于HashMap的更多信息请参考这位作者的文章:

    http://itindex.net/detail/46645-hashmap-%E8%A7%A3%E6%9E%90

 

 

 

  • 大小: 217.7 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics