2016-07-11 12 views
1

Ich habe mehrere Java-Dokumente, die in der gleichen Sammlung "App" in Mongodb gespeichert sind. Meine Absicht ist es für die gemeinsamen Persistenz Aktionen (einfügen, finden, löschen ...). Das Problem tritt auf, wenn ich versuche, Repositories für nur eine der Klassen zu definieren, da das von mir definierte Repository alle Entitäten durchsuchen wird und ich ein Repository benötige, in dem ich alle Standard-Funktionen von mongorepository aufrufen kann (find, findAll) , findby ...). Meine Erklärung kann hart sein, zu verstehen, ist es das, was ich habe jetzt:Anpassen eines Spring MongoRepository - Filter nach Klasse

Base-Dokument:

@Document(collection = "app") 
@NoRepositoryBean 
public abstract class AbstractApplicationDocument {  
    @Id 
    public String mongoId; 
    // more variables, getters, setters... 
} 

Einer der Subdokumente (es werden viele).

@EqualsAndHashCode(callSuper=true) 
public class ClientApplicationDocument extends AbstractApplicationDocument 
{ 
    @Id 
    public String mongoId;  
} 

Base-Repository

@NoRepositoryBean 
public interface ApplicationRepository<T, ID extends Serializable> extends MongoRepository<T, ID> { 

} 

Erweiterte Repository (wo ich nach Klasse filtern möchten)

public interface HttpClientRepository extends ApplicationRepository<HttpClientDocument, String> { 
} 

Beispiel für temporäre Lösung, die Ich mag würde zu vermeiden, wenn ich die wiederverwenden können MongoDb Dienstprogramme

@Component 
public class HttpClientRepositoryImpl { 

    @Autowired 
    private HttpClientRepository clientRepo; 

    @Autowired 
    private MongoTemplate mongo; 

    public List<HttpClientDocument> findAll() {  
     Query query = new Query(); 
     query.addCriteria(Criteria.where("_class").is(HttpClientDocument.class.getName())); 
     mongo.getConverter(); 
     return mongo.find(query, HttpClientDocument.class,"app"); 
    } 
} 

Relevante Informationen in Großbuchstaben. Ich füge das hinzu, weil ich einige Lösungen gesehen habe, die für mich nicht gültig sind. Wahrscheinlich, weil sie verschiedene Bibliotheken verwenden:

compile("org.springframework.boot:spring-boot-starter-data-mongodb:${springBootVersion}") 
compile ("org.springframework:spring-context-support:4.1.8.RELEASE"); 

Gibt es eine einfache Lösung?

+0

Ihre Domain-Klasse 'AbstractApplicationDocument' benötigt kein' @ NoRepositoryBean'. Diese Annotation ist nur für die Verwendung als Repository-Schnittstelle vorgesehen. Warum verwenden Sie ein leeres intermediäres 'ApplicationRepository' anstatt Ihre Anwendungsrepositories direkt aus' MongoRepository' abzuleiten?Über mehrere Dokumente in einer Sammlung: Das ist eine Möglichkeit, die andere verwendet Abfrage nach Beispiel mit Typabgleich. – mp911de

+0

Anmerkung entfernt, danke. Dies ist mein erster Kontakt mit Mongo und einige Klassen sind nur eine Kopie von Beispielen, die ich gefunden habe. Die leere Schnittstelle ist da für weitere Erweiterungen (ich muss nur einigen Anwendungen einen Cache hinzufügen), aber ich habe gelesen, dass dies mit Schnittstellen nicht richtig funktioniert, also werde ich es wahrscheinlich wieder entfernen. Mehrere Dokumente in einer Sammlung sind die Mongo-Struktur, es gibt Leistungsgründe, um sie auf diese Weise zu halten (es wäre zu lange zu erklären). – user2525691

+0

Das Speichern mehrerer Dokumente (Strukturen) in einer Sammlung wird nicht in Frage gestellt. Es wurde eine Antwort zum Anpassen des MongoDB-Repository-Verhaltens hinzugefügt. – mp911de

Antwort

2

Sie können Spring Data-Repositorys auf verschiedene Arten anpassen. Sie können benutzerdefinierte Repository-Basisklassen bereitstellen oder custom implementation classes bereitstellen.

Für Ihre Frage im Besonderen, SimpleMongoRepository nicht Abfrage auf dem _class Feld einschränken. Im Folgenden finden Sie ein Beispiel für eine benutzerdefinierte Repository-Basisklasse, die die Abfrageart findAll so einschränkt, dass nur der deklarierte Entitätstyp verwendet wird.

Sie müssten dieses Muster auch für andere Methoden anwenden, die auf der Ebene MongoRepository deklariert sind, die Sie auf den bestimmten Klassentyp einschränken möchten.

@EnableMongoRepositories(repositoryBaseClass = MyMongoRepository.class) 
static class Config { 
} 

static class MyMongoRepository<T, ID extends Serializable> extends SimpleMongoRepository<T, ID> { 

    private final MongoEntityInformation<T, ID> metadata; 
    private final MongoOperations mongoOperations; 

    public MyMongoRepository(MongoEntityInformation<T, ID> metadata, MongoOperations mongoOperations) { 
     super(metadata, mongoOperations); 
     this.metadata = metadata; 
     this.mongoOperations = mongoOperations; 
    } 

    @Override 
    public List<T> findAll() { 

     Query query = new Query(); 
     query.restrict(this.metadata.getJavaType()); 

     return this.mongoOperations.find(query, this.metadata.getJavaType(), this.metadata.getCollectionName()); 
    } 
} 

findAll Abfragen beschränken jetzt den Klassentyp und Abfragen für eine z.B. ModelRepository extends MongoRepository<Model, String> würde wie folgt aussehen:

{ "_class" : { "$in" : [ "com.example.Model"]}} 

Query-Methoden mit @Query verwendet werden können, in dem Klassentyp (@Query("{'_class': ?0}")) passieren, aber es gibt keine Möglichkeit, den Klassentyp für abgeleitete Abfragemethoden (List<Model> findByFirstnameAndLastname(…)) ConTrain.

In unserem Jira gibt es einen open ticket, der die Typen des Repository einschränkt. Dieses spezielle Ticket ist mit polymorphen Abfragen verknüpft, bezieht sich jedoch im Wesentlichen auf Typeinschränkungen für Abfragemethoden.

+0

Danke, es ist ähnlich wie die Lösung, die ich versuchte, aber deine sieht eleganter aus. Wenn ein Ticket geöffnet ist, bedeutet das, dass ich nicht die Antwort finden werde, auf die ich gewartet habe, also ist dies zur Zeit die beste Lösung. – user2525691

+0

Sie können eine Stimme für das Ticket lassen oder Ihre Gedanken hinzufügen. – mp911de