0

我正在使用 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...
}

但是,当我去抓取 seasons 对象时,modelIds 是空的!我不知道为什么它不能从 BSON 那里抢到季节,它显然就在那里。任何帮助是极大的赞赏!

4

1 回答 1

0

由于多种原因,我无法让它工作:

  1. 一旦持久化到 mongoDB 以加载回对象,我就无法获取数据,该对象将始终为空。
  2. 在问题 #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 表示法。

于 2012-07-25T19:31:30.287 回答