播放 Morphia,无法获取(通用)嵌入对象的列表内容
Posted
技术标签:
【中文标题】播放 Morphia,无法获取(通用)嵌入对象的列表内容【英文标题】:Play Morphia, Cannot grab List Content of (Generic) Embedded Object 【发布时间】:2012-07-19 16:02:37 【问题描述】:我正在使用 Play Framework 1.2.5 和 morphia-1.2.9a 模块。我最初在我的模型上使用@Reference 注释,但由于 (lazy=true) 不适用于@Reference,我需要使用 ObjectIds 进行切换。为了减少返工和冗余,我创建了以下 MorphiaList:
package models.morphia;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import models.Team;
import org.bson.types.ObjectId;
import com.google.code.morphia.annotations.Embedded;
import com.google.code.morphia.annotations.Transient;
import play.modules.morphia.Model;
@Embedded
public class MorphiaList<T extends MorphiaModel> implements Iterable<T>
@Embedded("ids") private List<ObjectId> modelIds;
@Transient List<T> models;
public void sort()
this.getAll();
Collections.sort(models);
this.modelIds.clear();
for(T t:this.models)
this.modelIds.add((ObjectId)t.getId());
public MorphiaList()
this.models = new ArrayList<T>();
this.modelIds = new ArrayList<ObjectId>();
public int size()
System.out.println(modelIds.size());
return modelIds.size();
public boolean add(T model)
return (this.models.add(model) && this.modelIds.add((ObjectId) model.getId()));
public boolean remove(T model)
return (this.models.remove(model)&&this.modelIds.remove((ObjectId) model.getId()));
public boolean addAll(Collection<? extends T> models)
for(T model: models)
this.models.add(model);
this.modelIds.add((ObjectId) model.getId());
return false;
public List<T> getAll()
for(ObjectId oi: this.modelIds)
boolean found=false;
for(T model: models)
if(oi==model.getId())
found=true;
break;
if(!found)
models.add(T.<T>findById(oi));
return models;
public T get(int index)
ObjectId id = modelIds.get(index);
for(T model: models)
if(id == model.getId())
return model;
return T.<T>findById(id);
@Override
public Iterator<T> iterator()
return this.getModelIterator();
public Iterator<T> getModelIterator()
for(ObjectId oi: modelIds)
boolean found=false;
for(T model: models)
if(oi==model.getId())
found=true;
break;
if(!found)
models.add(T.<T>findById(oi));
return models.iterator();
public boolean isEmpty()
return this.modelIds.isEmpty();
public boolean contains(T t)
return this.modelIds.contains(t.getId());
MorphiaModel 很简单,我只需要它来实现 Comparable 以便我可以对列表进行排序:
package models.morphia;
import play.modules.morphia.Model;
public abstract class MorphiaModel<T extends MorphiaModel<T>> extends Model implements Comparable<T>
然后我在课堂上这样使用它:
@Entity
public class Organization extends Purchasable
@Embedded public MorphiaList<Season> seasons = new MorphiaList<Season>();
添加季节后,mongo 会显示预期:
"_id" : "$oid" : "50097c147aa33c43fa8136ee" ,
...other members...
"seasons" : "ids" : [ "$oid" : "50097c147aa33c43fa8136ed"] ,
...other members...
当我去抓取季节对象时,modelIds 是空的!我不知道为什么它不能从 BSON 那里抢到季节,它显然就在那里。非常感谢任何帮助!
【问题讨论】:
【参考方案1】:由于多种原因,我无法让它工作:
-
一旦持久化到 mongoDB 以加载回对象,我无法获取数据,该对象将始终为空。
在问题 #1 之后,我添加了一个私人列表,该列表将在查找时填充我的 MorphiaList 以绕过它。但是在将 id 放入 MorphiaList 之后,我无法弄清楚如何查找特定的集合。特别是当您考虑到我使用继承时,我有一些异构集合。
我的解决方案:对于每个引用列表,我都重写了:
@Reference public List<Season> seasons;
到这里:
@Transient public List<Season> seasons;
private List<ObjectId> _seasons = new ArrayList();
@Transient private List<Season> pSeasons;
public List<Season> getSeasons()
if(pSeasons==null)
if(_seasons.size()!=0)
pSeasons = Season.find().<Season>field("_id").in(_seasons).asList();
else
pSeasons = new ArrayList();
return pSeasons;
我还必须添加一个 @PrePersist 方法来检查列表访问:
@PrePersist void beforeSave()
if(pSeasons!=null)
_seasons.clear();
for(Season s: pSeasons)
_seasons.add((ObjectId)s.getId());
这个 beforeSave() 必须针对您在代码中拥有的每个额外的引用列表进行扩展。故事的寓意:
如果您使用 Play 的 morphia 模块,请不要使用 @Reference 表示法。
【讨论】:
以上是关于播放 Morphia,无法获取(通用)嵌入对象的列表内容的主要内容,如果未能解决你的问题,请参考以下文章
创建 Spotify 播放列表时无法在响应对象中获取播放列表 ID