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...
}

ただし、シーズン オブジェクトを取得しようとすると、modelIds が空です。BSON からシーズンを取得できない理由はわかりませんが、明らかにそこにあります。どんな助けでも大歓迎です!

4

1 に答える 1

0

複数の理由でこれを機能させることができませんでした:

  1. mongoDB に永続化されたデータをオブジェクトにロードして戻すことができませんでした。オブジェクトは常に null になります。
  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 に答える