Today, I found a problem that Morphia alwasy stores classname for embedded collection when updating it. Here is my POJO example :
@Entity(noClassnameStored = true)
@Indexes({@Index(name="idx_meta" , value="meta.n, meta.v"), @Index(name="idx_meta_creator", value="meta.c")})
public class ResourceDO {
@Id
private String systemId;
...
@Embedded
private Set<ResourceMetaDO> meta;
...
public Set<ResourceMetaDO> getMetaEntries(){
return meta;
}
}
@Embedded(concreteClass=ResourceMetaDO.class)
public class ResourceMetaDO {
//name
private String n;
//value
private String v;
//creator
private String c;
...
}
I mapped both ResourceDO.class and ResourceMetaDO.class at the startup of my application using Morphia.map().
When I used AdvancedDatastore.save() or AdvancedDatastore.insert() to save or update resource, all went well.
However when I tried to use the following codes to update the meta :
updateMeta( ResourceDO r )
{
Query<ResourceDO> query = ds.createQuery(ResourceDO.class).filter("_id", r.getSystemId() );
UpdateOperations<ResourceDO> update =ds.createUpdateOperations(ResourceDO.class).set("meta", r.getMetaEntries());
dao.getDatastore().update(query, update);
}
The meta was stored with classname. When I looked into UpdateOpsImpl.java :
protected void add(UpdateOperator op, String f, Object value, boolean convert) {
if (value == null)
throw new QueryException("Val cannot be null");
Object val = null;
MappedField mf = null;
if (validateNames || validateTypes) {
StringBuffer sb = new StringBuffer(f);
mf = Mapper.validate(clazz, mapr, sb, FilterOperator.EQUAL, val, validateNames, validateTypes);
f = sb.toString();
}
if (convert)
if (UpdateOperator.PULL_ALL.equals(op) && value instanceof List)
val = toDBObjList(mf, (List<?>) value);
else
val = mapr.toMongoObject(mf, null, value);
...
}
and Mapper.java
public Object toMongoObject(MappedField mf, MappedClass mc, Object value) {
Object mappedValue = value;
//convert the value to Key (DBRef) if the field is @Reference or type is Key/DBRef, or if the destination class is an @Entity
if ((mf!=null && ( mf.hasAnnotation(Reference.class) ||
mf.getType().isAssignableFrom(Key.class) ||
mf.getType().isAssignableFrom(DBRef.class))
) || (mc != null && mc.getEntityAnnotation() != null)) {
try {
Key<?> k = (value instanceof Key) ? (Key<?>)value : getKey(value);
mappedValue = keyToRef(k);
} catch (Exception e) {
log.debug("Error converting value(" + value + ") to reference.", e);
mappedValue = toMongoObject(value, false);
}
}//serialized
else if (mf!=null && mf.hasAnnotation(Serialized.class))
try {
mappedValue = Serializer.serialize(value, !mf.getAnnotation(Serialized.class).disableCompression());
} catch (IOException e) {
throw new RuntimeException(e);
}
//pass-through
else if (value instanceof DBObject)
mappedValue = value;
else {
mappedValue = toMongoObject(value, EmbeddedMapper.shouldSaveClassName(value, mappedValue, mf));
if (mappedValue instanceof DBObject && !EmbeddedMapper.shouldSaveClassName(value, mappedValue, mf))
((DBObject) mappedValue).removeField(CLASS_NAME_FIELDNAME);
}
return mappedValue;
}
and EmbeddedMapper.java
public static boolean shouldSaveClassName(Object rawVal, Object convertedVal, MappedField mf) {
if (rawVal == null || mf == null)
return true;
if (mf.isSingleValue())
return !(mf.getType().equals(rawVal.getClass()) && !(convertedVal instanceof BasicDBList));
else
if ( convertedVal != null &&
convertedVal instanceof DBObject &&
!mf.getSubClass().isInterface() &&
!Modifier.isAbstract(mf.getSubClass().getModifiers()) &&
mf.getSubClass().equals(rawVal.getClass()))
return false;
else
return true;
}
It will always store classname for embedded collection even you have definite concreteClass for the embedded field.
So , I swtiched to the following tagging :
@Entity(noClassnameStored = true)
public class ResourceMetaDO implements IMetaEntry {
@Id
private ObjectId id;
//name
private String n;
//value
private String v;
//creator
private String c;
...
}
It works now. And note the id filed will not be set automatically by morphia if you only use the ResourceMetaDO class as the embedded field of ResourceDO
分享到:
相关推荐
在Java开发中,Morphia是一个优秀的对象数据映射(ODM)框架,它简化了与MongoDB之间的交互,使得开发者可以像操作传统关系型数据库那样操作文档数据库。本文将深入探讨如何使用Morphia框架来操作MongoDB。 首先,...
morphia-0.99.jar 最新版本。
MongoDB是一个流行的开源、分布式文档数据库,而Morphia是一个Java对象数据映射(Object-Document Mapping, ODM)框架,用于简化与MongoDB的交互。在这个压缩文件中,我们有两个重要的jar包:mongo-2.7.3.jar和...
标题中的“morphia.jar”和“mongo.jar”指的是两个与MongoDB数据库操作相关的Java库文件。MongoDB是一个流行的开源、分布式文档型数据库,而Morphia则是Java开发人员用来操作MongoDB的一个对象数据映射(ODM)框架...
morphia基于mongodb的基本开发
morphia-1.3.2.jar
**标题:“Morphia和MongoDB学习总结<三>”** 在本文中,我们将深入探讨Morphia,一个用于Java的MongoDB对象数据映射(ODM)库,以及它如何与MongoDB数据库进行交互。Morphia简化了在MongoDB中存储和检索Java对象的...
Spring MVC、Morphia 和 MongoDB 是三个在Java开发中常用于构建Web应用程序的关键技术。Spring MVC 是Spring框架的一部分,提供了一种模型-视图-控制器(MVC)架构模式,帮助开发者组织和处理Web应用的业务逻辑。...
在本文中,我们将探讨MongoDB的ORM框架Morphia,并结合Spring Data MongoDB的使用来创建一个集成应用。ORM(对象关系映射)框架是将数据库操作转化为对象模型的方法,简化了开发过程,使得开发者可以专注于业务逻辑...
Morphia 是一个 Java 框架,它为 MongoDB 提供了对象数据映射(Object Data Mapping,简称 ODM)功能,使得开发者可以更方便地在 Java 对象与 MongoDB 文档之间进行转换。本篇文章将详细介绍如何使用 Morphia 和 ...
【Morphia开发简介】 Morphia是一款针对MongoDB数据库的Java对象关系映射(ORM)框架,它的主要目标是让Java开发者能够以面向对象的方式处理数据库操作,从而减轻数据库设计的复杂性,使开发者能更专注于业务逻辑。...
【MongoDB与Morphia简介】 MongoDB是一款流行的NoSQL数据库系统,以其灵活的数据模型、高可用性和可扩展性而受到广泛欢迎。Morphia是针对MongoDB的一个Java持久层框架,它提供了简单易用的API,使得开发者能够方便地...
morphia mongo db OR-mapping mongo db再带的CRUD 太麻烦了, 一个不错的框架 类似 Hibernate
Morphia 是一个 Java ORM(对象关系映射)库,用于简化 MongoDB 的数据操作,将数据模型与数据库文档之间的转换自动化。在本文中,我们将深入探讨如何使用 Morphia 进行 MongoDB 的操作。 首先,为了在 Java 项目中...
### Morphia使用问题及解决方案集锦 #### 一、使用update方法更新带有@Reference注解的集合字段 在使用Morphia框架时,经常会遇到需要更新具有`@Reference`注解的集合字段的情况。例如,在更新`UserGroup`中的成员...
**Morphia:一个NoSQL的ORM框架** Morphia是一个强大的Java ORM(对象关系映射)框架,专为MongoDB数据库设计。它允许开发者使用Java对象来操作数据库,消除了与传统SQL数据库交互时所需的SQL语法,使开发更加便捷...
后续提交放在https://github.com/zdsiyan/watermelon 上, 用eclipse导入该工程需安装m2eclipse,jetty等查件. 另外.settings下的org.eclipse.wst.common.component文件如下: ...</project-modules>
**Morphia 概述** Morphia 是一个基于 Java 的开源对象数据映射(Object Document Mapping,简称 ODM)框架,它为 MongoDB 提供了简单易用的接口。MongoDB 是一个流行的分布式文档数据库系统,它以 JSON 格式存储...