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.