sql >> Database >  >> NoSQL >> MongoDB

Inleiding tot Spring Data MongoDB

1. Overzicht

Dit artikel is een snelle en praktische inleiding tot Spring Data MongoDB.

We bespreken de basis met zowel de MongoTemplate evenals MongoRepository , met praktische voorbeelden om elke bewerking te illustreren.


Verder lezen:

Geospatiale ondersteuning in MongoDB

Bekijk hoe u ruimtelijke gegevens kunt opslaan, indexeren en doorzoeken met MongoDBLees meer →

Spring Boot-integratietesten met Embedded MongoDB

Leer hoe u de ingebouwde MongoDB-oplossing van Flapdoodle samen met Spring Boot kunt gebruiken om MongoDB-integratietests soepel uit te voeren.Lees meer →

2. MongoTemplate enMongoRepository

De MongoTemplate volgt het standaardsjabloonpatroon in Spring en biedt een kant-en-klare, basis-API voor de onderliggende persistentie-engine.

De repository volgt de Spring Data-centric benadering en wordt geleverd met flexibelere en complexere API-bewerkingen, gebaseerd op de bekende toegangspatronen in alle Spring Data-projecten.

Voor beide moeten we beginnen met het definiëren van de afhankelijkheid — bijvoorbeeld in de pom.xml , met Maven:

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

Volg de releases hier om te controleren of er een nieuwe versie van de bibliotheek is uitgebracht.

3. Configuratie voor MongoTemplate

3.1. XML-configuratie

Laten we beginnen met de eenvoudige XML-configuratie voor de Mongo-sjabloon:

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

We moeten eerst de fabrieksbean definiëren die verantwoordelijk is voor het maken van Mongo-instanties.

Vervolgens moeten we de templatebean daadwerkelijk definiëren (en configureren):

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

En tot slot moeten we een postprocessor definiëren om alle MongoExceptions te vertalen in @Repository gegooid geannoteerde klassen:

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

3.2. Java-configuratie

Laten we nu een vergelijkbare configuratie maken met Java-configuratie door de basisklasse voor MongoDB-configuratie uit te breiden 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");
    }
}

Merk op dat we MongoTemplate niet hoefden te definiëren bean in de vorige configuratie omdat deze al is gedefinieerd in AbstractMongoClientConfiguration .

We kunnen onze configuratie ook helemaal opnieuw gebruiken zonder AbstractMongoClientConfiguration uit te breiden :

@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. Configuratie voor MongoRepository

4.1. XML-configuratie

Om gebruik te maken van aangepaste repositories (uitbreiding van de MongoRepository ), moeten we doorgaan met de configuratie van sectie 3.1. en stel de opslagplaatsen in:

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

4.2. Java-configuratie

Op dezelfde manier bouwen we voort op de configuratie die we al in paragraaf 3.2 hebben gemaakt. en voeg een nieuwe annotatie toe aan de mix:

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

4.3. Maak de repository

Na de configuratie moeten we een repository maken — het uitbreiden van de bestaande MongoRepository interface:

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

Nu kunnen we deze UserRepository automatisch bedraden en gebruik bewerkingen van MongoRepository of voeg aangepaste bewerkingen toe.

5. MongoTemplate gebruiken

5.1. Insert

Laten we beginnen met de invoegbewerking en een lege database:

{
}

Als we nu een nieuwe gebruiker toevoegen:

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

de database ziet er als volgt uit:

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

5.2. Opslaan – Invoegen

Het opslaan operatie heeft save-or-update semantiek:als een id aanwezig is, voert het een update uit, en zo niet, dan doet het een insert.

Laten we eens kijken naar de eerste semantiek — het invoegsel.

Dit is de beginstatus van de database:

{
}

Wanneer we nu opslaan een nieuwe gebruiker:

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

de entiteit wordt in de database ingevoegd:

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

Vervolgens bekijken we dezelfde bewerking — opslaan — met update-semantiek.

5.3. Opslaan – Bijwerken

Laten we nu eens kijken naar opslaan met update-semantiek, werkend op een bestaande entiteit:

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

Wanneer we opslaan de bestaande gebruiker, zullen we deze bijwerken:

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

De database ziet er als volgt uit:

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

We kunnen zien dat in dit specifieke voorbeeld, opslaan gebruikt de semantiek van update omdat we een object gebruiken met gegeven _id .

5.4. UpdateFirst

updateFirst werkt het allereerste document bij dat overeenkomt met de zoekopdracht.

Laten we beginnen met de beginstatus van de database:

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

Wanneer we nu de updateFirst . uitvoeren :

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);

alleen de eerste invoer wordt bijgewerkt:

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

5.5. UpdateMulti

UpdateMulti werkt alle documenten bij die overeenkomen met de opgegeven zoekopdracht.

Ten eerste, hier is de staat van de database voordat u de updateMulti . uitvoert :

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

Laten we nu de updateMulti . uitvoeren bediening:

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);

Beide bestaande objecten worden bijgewerkt in de database:

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

5.6. FindAndModify

Deze bewerking werkt als updateMulti , maar het retourneert het object voordat het werd gewijzigd.

Ten eerste is dit de status van de database voordat findAndModify wordt aangeroepen :

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

Laten we eens kijken naar de daadwerkelijke bewerkingscode:

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);

Het geretourneerde gebruikersobject heeft dezelfde waarden als de beginstatus in de database.

Dit is echter de nieuwe status in de database:

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

5.7. Upsert

De upsert werkt aan de zoek en wijzig else create semantiek :als het document overeenkomt, werk het dan bij of maak een nieuw document door de query en het update-object te combineren.

Laten we beginnen met de beginstatus van de database:

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

Laten we nu de upsert . uitvoeren :

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);

Hier is de staat van de database na de operatie:

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

5.8. Verwijderen

We kijken naar de status van de database voordat we verwijderen . aanroepen :

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

Laten we nu verwijderen . uitvoeren :

mongoTemplate.remove(user, "user");

Het resultaat zal zijn zoals verwacht:

{
}

6. MongoRepository gebruiken

6.1. Invoegen

Eerst zullen we de staat van de database zien voordat we de insert . uitvoeren :

{
}

Nu voegen we een nieuwe gebruiker toe:

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

En hier is de eindstatus van de database:

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

Merk op hoe de bewerking hetzelfde werkt als de insert in de MongoTemplate API.

6.2. Opslaan Invoegen

Op dezelfde manier opslaan werkt hetzelfde als de opslaan bewerking in de MongoTemplate API.

Laten we beginnen met te kijken naar de invoegsemantiek van de operatie.

Dit is de beginstatus van de database:

{
}

Nu voeren we de opslaan . uit bediening:

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

Dit resulteert in het toevoegen van de gebruiker aan de database:

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

Merk nogmaals op hoe opslaan werkt met insert semantiek omdat we een nieuw object invoegen.

6.3. Opslaan Bijwerken

Laten we nu naar dezelfde bewerking kijken, maar met semantiek bijwerken.

Ten eerste, hier is de status van de database voordat de nieuwe opslaan . wordt uitgevoerd :

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

Nu voeren we de bewerking uit:

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

Ten slotte is hier de status van de database:

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

Merk nogmaals op hoe opslaan werkt met update semantiek omdat we een bestaand object gebruiken.

6.4. Verwijderen

Dit is de status van de database voordat u delete aanroept :

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

Laten we verwijderen uitvoeren :

userRepository.delete(user);

En hier is ons resultaat:

{
}

6.5. FindOne

Vervolgens is dit de status van de database wanneer findOne heet:

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

Laten we nu de findOne . uitvoeren :

userRepository.findOne(user.getId())

En het resultaat zal de bestaande gegevens retourneren:

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

6.6. Bestaat

De status van de database voordat bestaat :

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

Laten we nu bestaat uitvoeren , wat natuurlijk true zal retourneren :

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

6.7. Alles zoeken MetSorteren

De status van de database voordat findAll . wordt aangeroepen :

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

Laten we nu findAll . uitvoeren metSorteren :

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

Het resultaat wordt gesorteerd op naam in oplopende volgorde :

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

6.8. Alles zoeken Met Pageable

De status van de database voordat findAll . wordt aangeroepen :

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

Laten we nu findAll . uitvoeren met een pagineringsverzoek:

Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();

De resulterende gebruikers lijst zal slechts één gebruiker zijn:

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

7. Annotaties

Laten we tot slot ook eens kijken naar de eenvoudige annotaties die Spring Data gebruikt om deze API-bewerkingen aan te sturen.

Het veldniveau @Id annotatie kan elk type versieren, inclusief lang en string :

@Id
private String id;

Als de waarde van de @Id veld is niet null, het is opgeslagen in de database zoals het is; anders gaat de converter ervan uit dat we een ObjectId . willen opslaan in de database (ofwelObjectId , Tekenreeks of BigInteger werk).

We zullen vervolgens kijken naar @Document :

@Document
public class User {
    //
}

Deze annotatie markeert een klasse eenvoudig als een domeinobject die moet worden bewaard in de database, samen met ons toelaten om de naam van de te gebruiken collectie te kiezen.


  1. Is de opdracht UNLINK altijd beter dan de opdracht DEL?

  2. Redis installeren op Debian 9

  3. Wanneer moet u Transparent Huge Pages uitschakelen voor redis

  4. Een inleiding tot MongoDB Zone Basics