Introduktion til Spring Data MongoDB

1. Oversigt

Denne artikel vil være en hurtig og praktisk introduktion til Spring Data MongoDB.

Vi gennemgår det grundlæggende ved hjælp af begge MongoTemplate såvel som MongoRepository ved hjælp af praktiske eksempler til at illustrere hver operation.

2. MongoTemplateog MongoRepository

Det MongoTemplatefølger standardskabelonmønsteret om foråret og giver en klar, grundlæggende API til den underliggende persistensmotor.

Datalageret følger Spring Data-centreret tilgang og kommer med mere fleksible og komplekse API-operationer baseret på de velkendte adgangsmønstre i alle Spring Data-projekter.

For begge er vi nødt til at starte med at definere afhængighed - for eksempel i pom.xml, med Maven:

 org.springframework.data spring-data-mongodb 3.0.3.RELEASE 

For at kontrollere om der er frigivet en ny version af biblioteket - følg udgivelserne her.

3. Konfiguration til MongoTemplate

3.1. XML-konfiguration

Lad os starte med den enkle XML-konfiguration til Mongo-skabelonen:

Først skal vi definere fabriksbønner, der er ansvarlige for oprettelse af Mongo-forekomster.

Dernæst - vi skal faktisk definere (og konfigurere) skabelonbønnen:

Og endelig er vi nødt til at definere en postprocessor til at oversætte enhver MongoUndtagelser kastet ind @Repository kommenterede klasser:

3.2. Java-konfiguration

Lad os nu oprette en lignende konfiguration ved hjælp af Java config ved at udvide basisklassen til MongoDB-konfiguration AbstractMongoConfiguration:

@Configuration offentlig klasse MongoConfig udvider AbstractMongoClientConfiguration {@ Override beskyttet String getDatabaseName () {return "test"; } @ Override public MongoClient mongoClient () {ConnectionString connectionString = new ConnectionString ("mongodb: // localhost: 27017 / test"); MongoClientSettings mongoClientSettings = MongoClientSettings.builder () .applyConnectionString (connectionString) .build (); returner MongoClients.create (mongoClientSettings); } @ Override offentlig samling getMappingBasePackages () {returner Collections.singleton ("com.baeldung"); }}

Bemærk: Vi behøvede ikke at definere MongoTemplate bønne i den tidligere konfiguration, som den allerede er defineret i AbstractMongoClientConfiguration.

Vi kan også bruge vores konfiguration fra bunden uden at udvide AbstractMongoClientConfiguration - som følger:

@Configuration public class SimpleMongoConfig {@Bean public MongoClient mongo () {ConnectionString connectionString = new ConnectionString ("mongodb: // localhost: 27017 / test"); MongoClientSettings mongoClientSettings = MongoClientSettings.builder () .applyConnectionString (connectionString) .build (); returner MongoClients.create (mongoClientSettings); } @Bean offentlig MongoTemplate mongoTemplate () kaster Undtagelse {returner ny MongoTemplate (mongo (), "test"); }}

4. Konfiguration til MongoRepository

4.1. XML-konfiguration

For at gøre brug af brugerdefinerede arkiver (udvide MongoRepository) - vi er nødt til at fortsætte konfigurationen fra afsnit 3.1 og oprette arkiverne:

4.2. Java-konfiguration

På samme måde bygger vi på den konfiguration, vi allerede har oprettet i afsnit 3.2, og tilføjer en ny kommentar til blandingen:

@EnableMongoRepositories (basePackages = "com.baeldung.repository") 

4.3. Opret lageret

Nu efter konfigurationen skal vi oprette et lager - udvide det eksisterende MongoRepository grænseflade:

offentlig grænseflade UserRepository udvider MongoRepository {//}

Nu kan vi automatisk tilslutte dette UserRepository og bruge operationer fra MongoRepository eller tilføj brugerdefinerede operationer.

5. Brug MongoTemplate

5.1. Indsæt

Lad os starte med indsætningsoperationen; lad os også starte med en tom database:

{ }

Nu, hvis vi indsætter en ny bruger:

Brugerbruger = ny bruger (); user.setName ("Jon"); mongoTemplate.insert (bruger, "bruger");

Databasen vil se sådan ud:

{"_id": ObjectId ("55b4fda5830b550a8c2ca25a"), "_class": "com.baeldung.model.User", "name": "Jon"}

5.2. Gem - Indsæt

Det Gemme operation har gem-eller-opdater-semantik: Hvis en id er til stede, udfører den en opdatering, hvis ikke - den indsætter.

Lad os se på den første semantik - indsatsen; her er databasens oprindelige tilstand:

{ }

Når vi nu Gemme en ny bruger:

Brugerbruger = ny bruger (); user.setName ("Albert"); mongoTemplate.save (bruger, "bruger");

Enheden indsættes i databasen:

{"_id": ObjectId ("55b52bb7830b8c9b544b6ad5"), "_class": "com.baeldung.model.User", "name": "Albert"}

Dernæst ser vi på den samme operation - Gemme - med opdateringssemantik.

5.3. Gem - Opdater

Lad os nu se på Gemme med opdateringssemantik, der opererer på en eksisterende enhed:

{"_id": ObjectId ("55b52bb7830b8c9b544b6ad5"), "_class": "com.baeldung.model.User", "name": "Jack"}

Nu, når vi Gemme den eksisterende bruger - vi opdaterer den:

bruger = mongoTemplate.findOne (Query.query (Criteria.where ("name"). er ("Jack")), User.class); user.setName ("Jim"); mongoTemplate.save (bruger, "bruger");

Databasen vil se sådan ud:

{"_id": ObjectId ("55b52bb7830b8c9b544b6ad5"), "_class": "com.baeldung.model.User", "name": "Jim"}

Som du kan se, i dette særlige eksempel, Gemme bruger semantikken i opdatering, fordi vi bruger et objekt med givet _id.

5.4. UpdateFirst

updateFirst opdaterer det allerførste dokument, der matcher forespørgslen.

Lad os starte med den oprindelige tilstand for databasen:

[{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Alex"}, {"_id": ObjectId ("55b5ffa5511fee0e45ed614c"), "_class ":" com.baeldung.model.User "," name ":" Alex "}]

Når vi nu kører updateFirst:

Forespørgsel = ny forespørgsel (); query.addCriteria (Criteria.where ("navn"). er ("Alex")); Opdater opdatering = ny opdatering (); update.set ("navn", "James"); mongoTemplate.updateFirst (forespørgsel, opdatering, User.class);

Kun den første post opdateres:

[{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "James"}, {"_id": ObjectId ("55b5ffa5511fee0e45ed614c"), "_class ":" com.baeldung.model.User "," name ":" Alex "}]

5.5. UpdateMulti

UpdateMultiopdaterer alt dokument, der matcher den givne forespørgsel.

Først - her er status for databasen, før du udfører opdaterMulti:

[{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Eugen"}, {"_id": ObjectId ("55b5ffa5511fee0e45ed614c"), "_class ":" com.baeldung.model.User "," name ":" Eugen "}] 

Lad os nu køre opdaterMulti operation:

Forespørgsel = ny forespørgsel (); query.addCriteria (Criteria.where ("navn"). er ("Eugen")); Opdater opdatering = ny opdatering (); update.set ("navn", "Victor"); mongoTemplate.updateMulti (forespørgsel, opdatering, User.class);

Begge eksisterende objekter opdateres i databasen:

[{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Victor"}, {"_id": ObjectId ("55b5ffa5511fee0e45ed614c"), "_class ":" com.baeldung.model.User "," name ":" Victor "}]

5.6. FindAndModify

Denne operation fungerer som opdaterMulti, men det returnerer objektet, før det blev ændret.

Først - databasens tilstand, inden du ringer findAndModify:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Markus"} 

Lad os se på den aktuelle driftskode:

Forespørgsel = ny forespørgsel (); query.addCriteria (Criteria.where ("navn"). er ("Markus")); Opdater opdatering = ny opdatering (); update.set ("navn", "Nick"); Brugerbruger = mongoTemplate.findAndModify (forespørgsel, opdatering, User.class);

De returnerede brugerobjekt har de samme værdier som den oprindelige tilstand i databasen.

Den nye tilstand i databasen er dog:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Nick"}

5.7. Upsert

Det opsving arbejder fungerer på finde og modificere andet skabe semantik: Hvis dokumentet matches, skal du opdatere det, ellers skal du oprette et nyt dokument ved at kombinere forespørgslen og opdatere objektet.

Lad os starte med den oprindelige tilstand for databasen:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Markus"}

Lad os nu køre opsving:

Forespørgsel = ny forespørgsel (); query.addCriteria (Criteria.where ("navn"). er ("Markus")); Opdater opdatering = ny opdatering (); update.set ("navn", "Nick"); mongoTemplate.upsert (forespørgsel, opdatering, User.class);

Her er status for databasen efter operationen:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Nick"}

5.8. Fjerne

Databasens tilstand, inden du ringer fjerne:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Benn"}

Lad os nu løbe fjerne:

mongoTemplate.remove (bruger, "bruger");

Resultatet bliver som forventet:

{ }

6. Brug MongoRepository

6.1. Indsæt

Først - status for databasen inden kørsel af indsæt:

{ }

Nu, når vi indsætter en ny bruger:

Brugerbruger = ny bruger (); user.setName ("Jon"); userRepository.insert (bruger); 

Her er sluttilstanden for databasen:

{"_id": ObjectId ("55b4fda5830b550a8c2ca25a"), "_class": "com.baeldung.model.User", "name": "Jon"}

Bemærk, hvordan operationen fungerer på samme måde som indsæt i MongoTemplate API.

6.2. Gemme Indsæt

Tilsvarende - Gemme fungerer det samme som Gemme drift i MongoTemplate API.

Lad os starte med at se på indsæt semantik af operationen her er databasens indledende tilstand:

{ }

Nu - vi udfører Gemme operation:

Brugerbruger = ny bruger (); user.setName ("Aaron"); userRepository.save (bruger);

Dette resulterer i, at brugeren føjes til databasen:

{"_id": ObjectId ("55b52bb7830b8c9b544b6ad5"), "_class": "com.baeldung.model.User", "name": "Aaron"}

Bemærk igen, hvordan i dette eksempel Gemme arbejder med indsæt semantik, fordi vi indsætter et nyt objekt.

6.3. Gemme Opdatering

Lad os nu se på den samme operation, men med opdater semantik.

Først - her er status for databasen, før den nye køres Gemme:

{"_id": ObjectId ("55b52bb7830b8c9b544b6ad5"), "_class": "com.baeldung.model.User", "name": "Jack" 81 * 6}

Nu - vi udfører operationen:

bruger = mongoTemplate.findOne (Query.query (Criteria.where ("name"). er ("Jack")), User.class); user.setName ("Jim"); userRepository.save (bruger);

Endelig er her databasens tilstand:

{"_id": ObjectId ("55b52bb7830b8c9b544b6ad5"), "_class": "com.baeldung.model.User", "name": "Jim"}

Bemærk igen, hvordan i dette eksempel Gemme arbejder med opdatering semantik, fordi vi bruger et eksisterende objekt.

6.4. Slet

Databasens tilstand inden du ringer slet:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Benn"}

Lad os løbe slet:

userRepository.delete (bruger); 

Resultatet bliver simpelthen:

{ }

6.5. FindOne

Databasens tilstand hvornår findOne Hedder:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Chris"}

Lad os nu udføre findOne:

userRepository.findOne (user.getId ()) 

Resultatet, som returnerer de eksisterende data:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Chris"}

6.6. Eksisterer

Databasens tilstand, inden du ringer eksisterer:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Harris"}

Lad os løbe nu eksisterer:

boolske isExists = userRepository.exists (user.getId ());

Som naturligvis vender tilbage rigtigt.

6.7. Find alle W med Sortere

Databasens tilstand inden du ringer findAlle:

[{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Brendan"}, {"_id": ObjectId ("67b5ffa5511fee0e45ed614b"), "_class ":" com.baeldung.model.User "," name ":" Adam "}]

Lad os nu løbe findAlle med Sortere:

Liste brugere = userRepository.findAll (Sort.by (Sort.Direction.ASC, "navn"));

Resultatet bliver sorteret efter navn i stigende rækkefølge:

[{"_id": ObjectId ("67b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Adam"}, {"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class ":" com.baeldung.model.User "," name ":" Brendan "}]

6.8. Find alle W med Sidelig

Databasens tilstand inden du ringer findAlle:

[{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Brendan"}, {"_id": ObjectId ("67b5ffa5511fee0e45ed614b"), "_class ":" com.baeldung.model.User "," name ":" Adam "}]

Lad os nu udføre findAlle med en pagineringsanmodning:

Pageable pageableRequest = PageRequest.of (0, 1); Side side = userRepository.findAll (pageableRequest); Liste brugere = pages.getContent ();

Den resulterende brugere listen vil kun være en bruger:

{"_id": ObjectId ("55b5ffa5511fee0e45ed614b"), "_class": "com.baeldung.model.User", "name": "Brendan"}

7. Kommentarer

Endelig lad os også gå over de enkle kommentarer, som Spring Data bruger til at drive disse API-operationer.

@Id privat streng-id;

Markniveauet @Id kommentar kan dekorere enhver type, inklusive lang og snor.

Hvis værdien af @Id felt er ikke nul, det er gemt i databasen som det er; Ellers antager konverteren, at du vil gemme en ObjectId i databasen (enten ObjectId, streng eller BigInteger arbejde).

Næste - @Dokument:

@Document offentlig klasse bruger {//}

Denne kommentar simpelthen markerer en klasse som et domæneobjekt der skal vedholdes i databasen sammen med at give os mulighed for at vælge navnet på den samling, der skal bruges.

8. Konklusion

Denne artikel var en hurtig, men omfattende introduktion til brug af MongoDB med Spring Data, både via MongoTemplate API samt brug af MongoRepository.

Implementeringen af ​​alle disse eksempler og kodestykker kan findes over på Github.