播放 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,无法获取(通用)嵌入对象的列表内容的主要内容,如果未能解决你的问题,请参考以下文章

Morphia:将MongoDb文档检索为Java对象

创建 Spotify 播放列表时无法在响应对象中获取播放列表 ID

播放上传的视频或嵌入 youtube 视频

mongodb morphia怎么获取最大的id

将查询结果插入 mysql 中的列时,无法从发送到 GEOMETRY 字段的数据中获取几何对象

玩!框架 1.2.4 - 从 morphia 立即保存