`

关于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
分享到:
评论

相关推荐

    MongoDB存储结构设计.pptx

    MongoDB存储结构设计是数据库架构中的一个重要议题,特别是在物联网(IoT)平台的背景下,它对于数据高效管理和处理至关重要。MongoDB是一种流行的NoSQL数据库,以其灵活性和高性能著称,但在设计存储结构时,需要考虑...

    Java操作mongoDB使用文档.docx(16页.docx

    MongoDB 是一个流行的开源NoSQL数据库,而Java Driver for MongoDB是官方提供的用于Java应用程序与MongoDB之间通信的库。在本文档中,我们将探讨如何使用Java驱动程序进行基本的MongoDB操作,包括连接、添加、更新、...

    java操作mongoDB查询的实例详解

    MongoDB是一个流行的NoSQL数据库系统,由C++编写,设计为分布式文件存储,特别适合处理大规模Web应用程序的数据存储需求。它提供了高性能、可扩展性和丰富的数据模型,尤其是对于非结构化或半结构化的数据。MongoDB...

    常见的面试点1

    5. 并发问题:HashMap在并发环境下可能导致死循环,因为1.7版本使用尾插法。1.8版本虽然使用头插法,但在并发情况下仍然不安全。面试中,你可能会被问到如何在并发环境中安全地使用HashMap,这时可以提到`HashTable`...

    JAVA面试很全的一个资料,不过仅针对面试哦,日常学习不合适。内容以问答形式。

    如JNI)、堆(存储对象实例,线程共享)以及方法区(存储类的元数据,如类名、字段、方法信息,旧版JVM中称为永久代,现代JVM已改用元空间)。 JVM运行时内存主要关注新生代、老年代和持久代。新生代用于存放新创建...

    电脑语言Redis学习总结.docx

    - **Hash**:类似于HashMap,适合存储结构化的数据,如用户信息,允许对单个字段进行操作。例如,使用`HSET`、`HGETALL`、`HLEN`等命令进行操作,`HSET`可用于更新已存在的键值对。 Redis的其他数据类型还包括Set...

    基于Spark的机器学习资料63、后台服务工具redis:详解redis操作命令.pdf

    * GETSET db mongodb:设定key的值,并返回旧值,没有旧值,返回nil hash(哈希) Redis hash是一个键值(key=&gt;value)对集合,特别适合用于存储对象。每个hash可以存储232-1键值对(约40亿)。 hash命令 * ...

    Java获取积分Java获取积分

    - 如果需要存储多个用户的积分,可以使用数组或集合(如ArrayList、HashMap等)来维护。 2. **用户身份验证**: - 在获取或更新积分前,通常需要验证用户身份,这可能涉及用户ID、会话管理(session)或令牌...

    Java通讯录源代码及设计资料

    6. **数据库集成**:更高级的实现可能会将数据存储在关系型数据库(如MySQL)或NoSQL数据库(如MongoDB)中,通过JDBC(Java Database Connectivity)接口与数据库进行交互,实现数据的CRUD(创建、读取、更新、删除...

    Java代码 ,RFID开发

    开发者可能定义一些类来表示RFID标签及其属性,使用集合框架如ArrayList或HashMap来存储大量数据。例如,创建一个`RFIDTag`类,包含EPC、读取时间、位置等字段,以及相关的方法。 在数据存储方面,Java可以与各种...

    Java网络爬虫

    这可能包括URL去重(使用HashSet或HashMap存储已访问的URL)和深度限制(限制爬虫访问的页面层级)。 数据存储方面,将抓取的信息保存到TXT文件是一个简单直接的方法。Java的FileWriter和BufferedWriter类可以用来...

    java面试题收集录--java面试没问题---来吧java对象

    3. **集合框架**:集合是存储和管理数据的关键,包括ArrayList、LinkedList、HashSet、HashMap等。面试中可能需要解释它们之间的区别,以及如何选择适当的集合类型。同时,了解并发容器如ConcurrentHashMap和...

    java实现简单通讯录

    这可以通过文件存储(如XML或JSON格式)、关系型数据库(如SQLite或MySQL)或者非关系型数据库(如MongoDB)来实现。如果选择文件存储,可以使用Java的序列化机制;如果是数据库,需要编写SQL语句或使用ORM框架(如...

    java面试大全,常见问题

    2. **集合框架**:Java集合框架包括List(如ArrayList和LinkedList)、Set(如HashSet和TreeSet)和Map(如HashMap和TreeMap)。面试中会考察对它们的区别、性能特点以及如何选择合适的数据结构来解决问题。 3. **...

    java面试题的总结

    13. **数据库**:SQL基础,包括查询优化、事务处理、索引、存储过程,以及NoSQL数据库如MongoDB的基本操作。 14. **算法与数据结构**:虽然不是Java语言本身的一部分,但作为程序员,理解基本的排序算法(如快速...

    Java获取全国所有省市列表.rar

    2. 静态资源:对于较小且不常变动的数据集,开发者可能选择将省市列表存储在Java的静态字段中,或者在程序启动时加载到内存的HashMap等数据结构中。 3. JSON文件:另一种常见的方式是将数据存储在JSON文件中,例如...

    缓存工具类

    1. **数据结构选择**:缓存通常使用哈希表(如HashMap)或者有序集合(如TreeMap)来存储数据,以实现快速查找。哈希表提供O(1)的查找效率,而有序集合则可以支持范围查询和按照某种排序规则访问。 2. **缓存策略**...

    学生信息管理系统

    使用JAVA的数据结构如ArrayList或HashMap可以存储学生对象,同时数据库中的表结构应与之对应,确保数据的一致性。 2. 成绩管理:系统应能记录和查询学生的考试成绩,可能包括多门课程的成绩。可以设计一个成绩实体...

    java程序员面试宝典和常见面试题

    2. **集合框架**:Java集合框架是面试中经常讨论的话题,包括List(ArrayList、LinkedList)、Set(HashSet、TreeSet)和Map(HashMap、LinkedHashMap、TreeMap)接口及其实现类,以及泛型、迭代器、比较器等概念。...

    Java面试.doc

    深入理解MySQL,包括索引、事务、存储引擎等,并熟悉NoSQL数据库如MongoDB。 **十五、缓存** Redis的使用,如缓存策略、数据结构和操作命令。 **十六、JVM** 了解JVM内存模型,垃圾回收机制,性能调优等。 **...

Global site tag (gtag.js) - Google Analytics