昨天晚上碰到了一个问题,弄了老半天后来在别人的帮助下发现是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
相关推荐
本文实例讲述了pymongo实现控制mongodb中数字字段做加法的方法。分享给大家供大家参考。具体分析如下: 这个非常实用,比如我们需要给文章做访问统计,可以设置一个数字字段:hit,然后每次点击后给改字段增加1即可 ...
本文主要介绍的是关于MongoDB动态字段设计的相关资料,分享出来供大家参考学习,需要的朋友们下面来一起看看详细的介绍吧。 适宜读者人群 MongoDB开发者 基础需求 产品: “我们要为现有的表单增加一个伟大的功能, ...
14、MongoDB存储原理&多文档事务详解_ev.rar14、MongoDB存储原理&多文档事务详解_ev.rar14、MongoDB存储原理&多文档事务详解_ev.rar14、MongoDB存储原理&多文档事务详解_ev.rar14、MongoDB存储原理&多文档事务详解_...
基于mongodb存储的军事领域知识图谱问答项目,8大类,100余小类,共计5800项的知识库,该项目不使用图数据库进行存储,通过jieba进行问句解析,问句实体项识别,基于查询模板完成多类问题的查询,主要是提供一种工业...
mongodb-field-level-encryption:使用Spring Boot 2在MongoDB中设置字段级加密
主要给大家介绍了关于MongoDB存储时间时差问题的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用mongodb具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Node.js 实践: 使用 MongoDB 存储数据 MongoDB命令行工具的使用 在项目中如何有效组织和使用Mongoose
MongoDB问文件存储,包括大文件存储
本文主要介绍了关于MongoDB存储数据的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 想要深入了解MongoDB如何存储数据之前,有一个概念必须清楚,那就是Memeory-Mapped Files。 Memeory-Mapped ...
唯一索引用于确保索引字段不存储重复的值,即强制索引字段的唯一性。缺省情况下,MongoDB的_id字段在创建集合的时候会自动创建一个唯一索引。本文主要描述唯一索引的用法。 关于什么是索引以及唯一索引这里就不做...
将一系列图片文件存储到MongoDB中 java操作mongodb存储文件
很全面的mongodb 查询语法和实例 $gt $lt $gte $lte $exists $size $type 等等
spring data mongodb的demo程序,参考App.java中的调用方法,mongodb配置文件在resources目录下,整个项目使用maven,适合初学者学习。
检查mongodb字段是否有重复值
QAonMilitaryKG - 基于mongodb领域知识图谱问答项目,该项目不使用图数据库进行存储,通过jieba进行问句解析,问句实体项识别,基于查询模板完成多类问题的查询,主要是提供一种工业界的问答思想demo。
本课程是一套关于MongoDB应用开发的实战性教程,名为《深入浅出MongoDB应用实战开发(基础、开发指南、系统管理、集群及系统架构)》,教程侧重于讲解MongoDB的常用特性及高级特性,从实际开发的角度出发对MongoDB...
Mongodb基于GridFS存储文件,通过流的方式存储文件图片,以及读取功能。本人亲自测试、编写。值得信赖
分布式存储数据库MongoDB教程