1. Översikt
Den här artikeln kommer att vara en snabb och praktisk introduktion till Spring Data MongoDB.
Vi går igenom grunderna med både MongoTemplate samt MongoRepository , med praktiska exempel för att illustrera varje operation.
Mer läsning:
Geospatialt stöd i MongoDB
Ta en titt på hur du lagrar, indexerar och söker geospatial data med MongoDB Läs mer →Spring Boot Integration Testing with Embedded MongoDB
Lär dig hur du använder Flapdoodles inbyggda MongoDB-lösning tillsammans med Spring Boot för att köra MongoDB-integreringstester smidigt. Läs mer →2. MongoTemplate och MongoRepository
Mongo-mallen följer standardmallmönstret under våren och tillhandahåller ett färdigt, grundläggande API till den underliggande persistensmotorn.
Förvaret följer Spring Data-centrerad tillvägagångssätt och kommer med mer flexibla och komplexa API-operationer, baserade på de välkända åtkomstmönstren i alla Spring Data-projekt.
För båda måste vi börja med att definiera beroendet – till exempel i pom.xml , med Maven:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
För att kontrollera om någon ny version av biblioteket har släppts, spåra utgivningarna här.
3. Konfiguration för MongoTemplate
3.1. XML-konfiguration
Låt oss börja med den enkla XML-konfigurationen för Mongo-mallen:
<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />
Vi måste först definiera fabriksbönan som är ansvarig för att skapa Mongo-instanser.
Därefter måste vi faktiskt definiera (och konfigurera) mallbönan:
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory"/>
</bean>
Och slutligen måste vi definiera en efterbehandlare för att översätta alla MongoExceptions kastas i @Repository kommenterade klasser:
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
3.2. Java-konfiguration
Låt oss nu skapa en liknande konfiguration med Java-konfiguration genom att utöka basklassen för 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");
}
}
Observera att vi inte behövde definiera MongoTemplate bean i den tidigare konfigurationen eftersom den redan är definierad i AbstractMongoClientConfiguration .
Vi kan också använda vår konfiguration från början utan att utöka 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 för MongoRepository
4.1. XML-konfiguration
För att använda anpassade arkiv (som utökar MongoRepository ), måste vi fortsätta konfigurationen från avsnitt 3.1. och ställ in arkiven:
<mongo:repositories
base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>
4.2. Java-konfiguration
På samma sätt kommer vi att bygga vidare på konfigurationen som vi redan skapat i avsnitt 3.2. och lägg till en ny kommentar i mixen:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Skapa arkivet
Efter konfigurationen måste vi skapa ett arkiv – förlänga det befintliga MongoRepository gränssnitt:
public interface UserRepository extends MongoRepository<User, String> {
//
}
Nu kan vi automatiskt koppla detta UserRepository och använd operationer från MongoRepository eller lägg till anpassade operationer.
5. Använder MongoTemplate
5.1. Infoga
Låt oss börja med insert-operationen samt en tom databas:
{
}
Om vi nu infogar en ny användare:
User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");
databasen kommer att se ut så här:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
5.2. Spara – Infoga
spara operationen har spara-eller-uppdatera semantik:om ett id finns, utför den en uppdatering, och om inte, infogar den.
Låt oss titta på den första semantiken — infogningen.
Här är det initiala tillståndet för databasen:
{
}
När vi nu spara en ny användare:
User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");
enheten kommer att infogas i databasen:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Albert"
}
Därefter ska vi titta på samma operation – spara — med uppdateringssemantik.
5.3. Spara – Uppdatera
Låt oss nu titta på spara med uppdateringssemantik, som fungerar på en befintlig enhet:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"
}
När vi spara den befintliga användaren kommer vi att uppdatera den:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
Databasen kommer att se ut så här:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Vi kan se att i det här exemplet spara använder semantiken för uppdatering eftersom vi använder ett objekt med angivet _id .
5.4. UpdateFirst
updateFirst uppdaterar det allra första dokumentet som matchar frågan.
Låt oss börja med databasens initiala tillstånd:
[
{
"_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ör 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);
endast den första posten kommer att uppdateras:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "James"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
5.5. UpdateMulti
UpdateMulti uppdaterar alla dokument som matchar den givna frågan.
Först, här är tillståndet för databasen innan du gör updateMulti :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
}
]
Låt oss nu köra 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);
Båda befintliga objekten kommer att uppdateras 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
Denna operation fungerar som updateMulti , men det returerar objektet innan det ändrades.
För det första är detta tillståndet för databasen innan findAndModify anropas :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Låt oss titta på den faktiska operationskoden:
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 returnerade användarobjektet har samma värden som initialtillståndet i databasen.
Detta är dock det nya tillståndet i databasen:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.7. Upsert
upsert fungerar på hitta och modifiera annat skapa semantik :om dokumentet matchas, uppdatera det eller skapa ett nytt dokument genom att kombinera frågan och uppdateringsobjektet.
Låt oss börja med databasens initiala tillstånd:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Låt oss nu köra 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);
Här är tillståndet för databasen efter operationen:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.8. Ta bort
Vi kommer att titta på tillståndet för databasen innan vi anropar remove :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Låt oss nu köra ta bort :
mongoTemplate.remove(user, "user");
Resultatet blir som förväntat:
{
}
6. Använder MongoRepository
6.1. Infoga
Först kommer vi att se tillståndet för databasen innan vi kör insert :
{
}
Nu kommer vi att infoga en ny användare:
User user = new User();
user.setName("Jon");
userRepository.insert(user);
Och här är sluttillståndet för databasen:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
Notera hur operationen fungerar på samma sätt som infogningen i MongoTemplate API.
6.2. Spara – Infoga
På samma sätt spara fungerar på samma sätt som spara operation i MongoTemplate API.
Låt oss börja med att titta på infogningens semantik av operationen.
Här är det initiala tillståndet för databasen:
{
}
Nu kör vi spara operation:
User user = new User();
user.setName("Aaron");
userRepository.save(user);
Detta resulterar i att användaren läggs till i databasen:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Aaron"
}
Notera igen hur du spara fungerar med insert semantik eftersom vi infogar ett nytt objekt.
6.3. Spara – Uppdatera
Låt oss nu titta på samma operation men med uppdatera semantik.
Först, här är tillståndet för databasen innan du kör det nya spara :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"81*6
}
Nu kör vi operationen:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);
Slutligen, här är tillståndet för databasen:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Notera igen hur du spara fungerar med uppdatering semantik eftersom vi använder ett befintligt objekt.
6.4. Ta bort
Här är tillståndet för databasen innan du anropar delete :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Låt oss köra delete :
userRepository.delete(user);
Och här är vårt resultat:
{
}
6.5. FindOne
Därefter är detta tillståndet för databasen när findOne heter:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
Låt oss nu köra findOne :
userRepository.findOne(user.getId())
Och resultatet kommer att returnera befintliga data:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
6.6. Finns
Databasens tillstånd före anrop finns :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Harris"
}
Låt oss nu köra exists , vilket naturligtvis kommer att returnera true :
boolean isExists = userRepository.exists(user.getId());
6.7. Hitta alla Med Sortera
Databasens tillstånd innan findAll anropas :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Låt oss nu köra findAll med Sortera :
List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
Resultatet kommer att sorteras efter namn i stigande ordning :
[
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
]
6.8. Hitta alla Med Sökbar
Databasens tillstånd innan findAll anropas :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Låt oss nu köra findAll med en pagineringsbegäran:
Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
De resulterande användarna listan kommer bara att vara en användare:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
7. Anteckningar
Slutligen, låt oss också gå igenom de enkla kommentarerna som Spring Data använder för att driva dessa API-operationer.
Fältnivån @Id anteckningar kan dekorera vilken typ som helst, inklusive lång och sträng :
@Id
private String id;
Om värdet på @Id fältet är inte null, det lagras i databasen som det är; annars kommer omvandlaren att anta att vi vill lagra ett ObjectId i databasen (antingen ObjectId , Sträng eller BigInteger arbete).
Vi ska nästa titta på @Document :
@Document
public class User {
//
}
Den här anteckningen markerar helt enkelt en klass som ett domänobjekt som måste finnas kvar i databasen, tillsammans med att vi kan välja namnet på samlingen som ska användas.