sql >> Database teknologi >  >> NoSQL >> MongoDB

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 at bruge både MongoTemplate samt MongoRepository , med praktiske eksempler til illustration af hver operation.


Yderligere læsning:

Geospatial support i MongoDB

Se, hvordan du gemmer, indekserer og søger geospatiale data med MongoDBRead more →

Spring Boot Integration Testing med Embedded MongoDB

Lær, hvordan du bruger Flapdoodles indlejrede MongoDB-løsning sammen med Spring Boot til at køre MongoDB-integrationstests problemfrit. Læs mere →

2. MongoTemplate og MongoRepository

MongoTemplate følger standardskabelonmønsteret i foråret og giver en klar til brug, grundlæggende API til den underliggende persistensmotor.

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

For begge skal vi starte med at definere afhængigheden - for eksempel i pom.xml , med Maven:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-mongodb</artifactId>
    <version>3.0.3.RELEASE</version>
</dependency>

For at kontrollere, om en ny version af biblioteket er blevet frigivet, kan du spore udgivelserne her.

3. Konfiguration for MongoTemplate

3.1. XML-konfiguration

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

<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />

Vi skal først definere fabriksbønnen, der er ansvarlig for at skabe Mongo-forekomster.

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

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> 
    <constructor-arg ref="mongoDbFactory"/> 
</bean>

Og endelig skal vi definere en postbehandler til at oversætte alle MongoExceptions smidt i @Repository kommenterede klasser:

<bean class=
  "org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

3.2. Java-konfiguration

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

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

Bemærk, at vi ikke behøvede at definere MongoTemplate bean i den tidligere konfiguration, da den allerede er defineret i AbstractMongoClientConfiguration .

Vi kan også bruge vores konfiguration fra bunden uden at udvide AbstractMongoClientConfiguration :

@Configuration
public class SimpleMongoConfig {
 
    @Bean
    public MongoClient mongo() {
        ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/test");
        MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
          .applyConnectionString(connectionString)
          .build();
        
        return MongoClients.create(mongoClientSettings);
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(mongo(), "test");
    }
}

4. Konfiguration for MongoRepository

4.1. XML-konfiguration

For at gøre brug af brugerdefinerede lagre (for at udvide MongoRepository ), skal vi fortsætte konfigurationen fra afsnit 3.1. og opsæt arkiverne:

<mongo:repositories 
  base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>

4.2. Java-konfiguration

På samme måde vil vi bygge videre på den konfiguration, vi allerede oprettede i afsnit 3.2. og tilføj en ny annotation til blandingen:

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

4.3. Opret repository

Efter konfigurationen er vi nødt til at oprette et depot – udvide det eksisterende MongoRepository grænseflade:

public interface UserRepository extends MongoRepository<User, String> {
    // 
}

Nu kan vi automatisk forbinde dette UserRepository og brug operationer fra MongoRepository eller tilføje brugerdefinerede handlinger.

5. Brug af MongoTemplate

5.1. Indsæt

Lad os starte med indsættelsesoperationen samt en tom database:

{
}

Hvis vi nu indsætter en ny bruger:

User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");

databasen vil se sådan ud:

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

5.2. Gem – Indsæt

Gem operationen har gem-eller-opdater semantik:hvis et id er til stede, udfører den en opdatering, og hvis ikke, udfører den en indsættelse.

Lad os se på den første semantik — indsættelsen.

Her er den oprindelige tilstand for databasen:

{
}

Når vi nu gemmer en ny bruger:

User user = new User();
user.setName("Albert"); 
mongoTemplate.save(user, "user");

enheden vil blive indsat i databasen:

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

Dernæst vil vi se på den samme handling - gem — med opdateringssemantik.

5.3. Gem – Opdater

Lad os nu se på gem med opdateringssemantik, der fungerer på en eksisterende enhed:

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

Når vi gemmer den eksisterende bruger, opdaterer vi den:

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

Databasen vil se sådan ud:

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

Vi kan se, at i dette særlige eksempel, gem bruger semantikken i opdatering fordi vi bruger et objekt med givet _id .

5.4. Opdater først

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

Lad os starte med databasens begyndelsestilstand:

[
    {
        "_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 :

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Alex"));
Update update = new Update();
update.set("name", "James");
mongoTemplate.updateFirst(query, update, User.class);

kun den første post vil blive opdateret:

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

5.5. UpdateMulti

UpdateMulti opdaterer alle dokumenter, der matcher den givne forespørgsel.

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

[
    {
        "_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 updateMulti operation:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eugen"));
Update update = new Update();
update.set("name", "Victor");
mongoTemplate.updateMulti(query, update, User.class);

Begge eksisterende objekter vil blive opdateret 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 handling fungerer som updateMulti , men det returnerer objektet, før det blev ændret.

For det første er dette databasens tilstand, før du kalder findAndModify :

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

Lad os se på den faktiske operationskode:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
User user = mongoTemplate.findAndModify(query, update, User.class);

Det returnerede brugerobjekt har de samme værdier som starttilstanden i databasen.

Dette er dog den nye tilstand i databasen:

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

5.7. Ophæv

upsert virker på find og modificer andet opret semantik :hvis dokumentet matches, skal du opdatere det, eller på anden måde oprette et nyt dokument ved at kombinere forespørgslen og opdateringsobjektet.

Lad os starte med databasens begyndelsestilstand:

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

Lad os nu køre upsert :

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
mongoTemplate.upsert(query, update, User.class);

Her er status for databasen efter operationen:

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

5.8. Fjern

Vi ser på databasens tilstand, før vi kalder fjern :

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

Lad os nu køre fjern :

mongoTemplate.remove(user, "user");

Resultatet bliver som forventet:

{
}

6. Brug af MongoRepository

6.1. Indsæt

Først vil vi se databasens tilstand, før vi kører indsæt :

{
}

Nu vil vi indsætte en ny bruger:

User user = new User();
user.setName("Jon");
userRepository.insert(user);

Og her er sluttilstanden for databasen:

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

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

6.2. Gem Indsæt

På samme måde gem fungerer på samme måde som gem operation i MongoTemplate API.

Lad os starte med at se på indsæt-semantikken af operationen.

Her er den oprindelige tilstand af databasen:

{
}

Nu udfører vi gem operation:

User user = new User();
user.setName("Aaron");
userRepository.save(user);

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

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

Bemærk igen hvordan gem fungerer med insert semantik, fordi vi indsætter et nyt objekt.

6.3. Gem Opdatering

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

Først, her er status for databasen, før du kører den nye gem :

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

Nu udfører vi handlingen:

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

Endelig er her databasens tilstand:

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

Bemærk igen hvordan gem fungerer med opdatering semantik, fordi vi bruger et eksisterende objekt.

6.4. Slet

Her er status for databasen, før du kalder delete :

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

Lad os køre slet :

userRepository.delete(user);

Og her er vores resultat:

{
}

6.5. FindOne

Dernæst er dette databasens tilstand, når findOne hedder:

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

Lad os nu udføre findOne :

userRepository.findOne(user.getId())

Og resultatet vil returnere de eksisterende data:

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

6.6. Eksisterer

Status for databasen før opkald findes :

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

Lad os nu køre eksisterer , som naturligvis vil returnere sand :

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

6.7. Find alle Med Sorter

Status for databasen før kald findAll :

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

Lad os nu køre findAlle med Sorter :

List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));

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 Med Sidebar

Status for databasen før kald findAll :

[
    {
        "_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);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();

De resulterende brugere listen vil kun være én bruger:

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

7. Anmærkninger

Lad os endelig også gennemgå de simple annotationer, som Spring Data bruger til at drive disse API-operationer.

Feltniveauet @Id annotering kan dekorere enhver type, inklusive lang og streng :

@Id
private String id;

Hvis værdien af ​​@Id feltet er ikke null, det er gemt i databasen, som det er; ellers vil konverteren antage, at vi ønsker at gemme et ObjectId i databasen (enten ObjectId , Streng eller BigInteger arbejde).

Vi vil derefter se på @Document :

@Document
public class User {
    //
}

Denne annotation markerer simpelthen en klasse som værende et domæneobjekt som skal bevares i databasen, sammen med at vi kan vælge navnet på den samling, der skal bruges.


  1. Redis-statistik

  2. C# - MongoDB - Opdater et element i et indlejret dokument

  3. MongoDB $konverter

  4. Hvordan kan jeg gennemse eller forespørge om live MongoDB-data?