2010-07-21 11 views
5

Ho un classi del modello comeCome ottenere un elenco correttamente digitato da un ReflectionDBObject

public class MyClass extends ReflectionDBObject { 
    private List<NiceAttribute> attributes;  
    ... 
} 

public class NiceAttribute extends ReflectionDBObject { 
    ... 
} 

creo in un modo typesafe, come

List<NiceAttribute> attrs = new ArrayList<NiceAttribute>(); 
attrs.add(new NiceAttribute()); 
MyClass myClass = new MyClass(); 
myClass.setAttributes(attrs); 

quindi salvarlo mongo, e recuperare con un codice come

DBCollection col = ...; 
col.setObjectClass(MyClass.class) 
MyClass foundObject = (MyClass)col.findOne(); 

Ma il problema è che foundObject s' attributes diventa una lista di BasicDBObject. Sembra che un driver non possa (o non voglia) rilevare un tipo di elementi dell'elenco. Si tratta di una limitazione del driver o mi sono perso qualcosa? Quale sarebbe un'elegante soluzione alternativa al problema?

BTW, so di Morphia ecc. Forse risolve il problema. Ma il mio progetto è minuscolo e non voglio complicare le cose con un ulteriore livello di astrazione.

risposta

-1

È necessario utilizzare Morphia. Aggiunge il supporto per POJO e oggetti incorporati (e raccolte). Non ha nessuna delle limitazioni che il driver fa circa il fatto che le tue classi assomiglino a un Map<String, Object>.

+0

Morphia è di circa 10-15 volte più lento del conducente. Stai meglio scrivendo il tuo codice per fare la mappatura. –

+0

Abbiamo test delle prestazioni in morfina che dimostra che questo non è vero. Se si dispone di alcuni test che mostrano questo problema di prestazioni, sarebbe opportuno condividerli. –

+0

In realtà ho fatto test molto basilari, in cui scrivo la stessa voce circa 10-20k volte, usando driver, poi Spring Mongo Db poi Morphia. Il driver è il più veloce, Spring Mongo è circa 2 volte più lento e la morfina è circa 7-10 volte più lenta. Anche su un mongo con reale raccolta di frammenti (su più macchine) è ancora più lento. Puoi facilmente testarlo. –

4

Beh, c'è una soluzione, ma non ti piacerà. Fondamentalmente puoi specificare la classe corrispondente per un percorso interno all'interno del tuo oggetto. Ecco quello che ho fatto, e funziona:

public class Release extends ReflectionDBObject { 

    //other fields omitted  

    private List<ReleaseDetailsByTerritory> releaseDetailsByTerritory = new ArrayList<ReleaseDetailsByTerritory>(); 

} 

public class ReleaseDetailsByTerritory extends ReflectionDBObject { //...} 

Ora, se ho semplicemente fare questo:

releaseColl.setObjectClass(Release.class); 
    releaseColl.setInternalClass("ReleaseDetailsByTerritory.0", ReleaseDetailsByTerritory.class); 
    Release r = (Release) releaseColl.findOne(); 
    //the internal list will contain ReleaseDetailsByTerritory type objects (not DBObjects) 
    System.out.println(r.getReleaseDetailsByTerritory().get(0).getClass().getName()); 

La cosa schifosa è che non si può (o almeno non ho trovato come) per specificare la classe di mappatura per TUTTI gli elementi di un array incorporato. Non si può fare qualcosa di simile:

releaseColl.setInternalClass("ReleaseDetailsByTerritory", ReleaseDetailsByTerritory.class); 

o

releaseColl.setInternalClass("ReleaseDetailsByTerritory.*", ReleaseDetailsByTerritory.class); 

Bisogna invece per specificare la classe mappatura di ogni possibile elemento dell'array incorporato:

releaseColl.setInternalClass("ReleaseDetailsByTerritory.0", ReleaseDetailsByTerritory.class); 
releaseColl.setInternalClass("ReleaseDetailsByTerritory.1", ReleaseDetailsByTerritory.class); 
releaseColl.setInternalClass("ReleaseDetailsByTerritory.2", ReleaseDetailsByTerritory.class); 
Problemi correlati