2015-01-19 8 views
6

Avere due tipi di entità, che sono mappati a due classi Java nella collezione singolo MongoDB:primavera dati MongoDB repository non implementano correttamente eredità

@Document 
public class Superclass { ... } 

@Document(collection = "superclass") 
public class Subclass extends Superclass { ... } 

e due depositi per quelle entità:

public interface SuperclassRepository extends MongoRepository<Superclass, String> {} 
public interface SubclassRepository extends MongoRepository<Subclass, String> {} 

MongoRepositories non gestiscono correttamente l'ereditarietà delle entità. Durante l'interrogazione per tutte Subclass gli oggetti (ad esempio SubclassRepository.findAll()) il set di risultati contiene Superclass oggetti, cui si crea un'istanza (o almeno era stato trovato a essere istanziata) con valori nulli per i campi che fanno parte del Subclass, ma non sono parte del Superclass .

Il risultato previsto sarebbe che SubclassRepository deve restituire solo Subclass oggetti, mentre SuperclassRepository dovrebbe restituire Superclass e Subclass oggetti. Funziona in questo modo in Spring Data JPA.

Qualcuno ha riscontrato questo bug e ha qualche soluzione su come risolverlo?

+0

ho creato un [biglietti] (https://jira.spring.io/brows e/DATAMONGO-1142) e la [richiesta pull] (https://github.com/spring-projects/spring-data-mongodb/pull/266) per quell'errore. –

risposta

3

Ho riscontrato lo stesso problema.

Dai un'occhiata al codice sorgente e con mia sorpresa è un po 'non implementato. Aggiunge il nome della raccolta e la classe di entità, ma non ha inserito nella query finale la proprietà _class. E dopo averlo dato un'occhiata mi sono reso conto di come Mongo avrebbe saputo che SubClass1 o Sottoclasse2 derivavano dalla SuperClass. Così ho appena sostituire la classe SimpleMongoRepository e creare il mio fabbrica che ha messo quella classe al posto del default SimpleMongoRepository

Ecco quello che ho aggiunto:

public MySimpleMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) { 

    Assert.notNull(mongoOperations); 
    Assert.notNull(metadata); 

    this.entityInformation = metadata; 
    this.mongoOperations = mongoOperations; 
    Reflections reflections = new Reflections("com.cre8techlabs.entity"); 
    Set<String> subTypes = reflections.getSubTypesOf(entityInformation.getJavaType()).stream().map(Class::getName).collect(Collectors.toSet()); 
    subTypes.add(entityInformation.getJavaType().getName()); 
    this.baseClassQuery = Criteria.where("_class").in(subTypes.toArray()); 
} 

Ed ecco un esempio di implementazione di un trovare

public T findOne(ID id) { 
    Assert.notNull(id, "The given id must not be null!"); 
    Query q = getIdQuery(id).addCriteria(baseClassQuery); 

    return mongoOperations.findOne(q, entityInformation.getJavaType(), entityInformation.getCollectionName()); 
} 

funziona per me, io sono solo paura che ci vuole un po 'di più

+1

L'ideale sarebbe cambiare QueryMapper, ma significherà cambiare il MongoTemplate –

Problemi correlati