1. Przegląd
Ten artykuł będzie szybkim i praktycznym wprowadzeniem do Spring Data MongoDB.
Omówimy podstawy, korzystając z MongoTemplate a także MongoRepository , z praktycznymi przykładami ilustrującymi każdą operację.
Dalsza lektura:
Obsługa geoprzestrzenna w MongoDB
Zobacz, jak przechowywać, indeksować i przeszukiwać dane geoprzestrzenne za pomocą MongoDBCzytaj więcej →Testowanie integracji Spring Boot z wbudowaną MongoDB
Dowiedz się, jak korzystać z wbudowanego rozwiązania MongoDB Flapdoodle razem z Spring Boot, aby płynnie przeprowadzać testy integracji MongoDB. Czytaj więcej →2. MongoTemplate iMongoRepository
Szablon Mongo jest zgodny ze standardowym wzorcem szablonu w Spring i zapewnia gotowy, podstawowy interfejs API do bazowego silnika trwałości.
Repozytorium jest zgodny z podejściem Spring Data-centric i zawiera bardziej elastyczne i złożone operacje API, oparte na dobrze znanych wzorcach dostępu we wszystkich projektach Spring Data.
W obu przypadkach musimy zacząć od zdefiniowania zależności — na przykład w pliku pom.xml , z Mavenem:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
Aby sprawdzić, czy została wydana jakakolwiek nowa wersja biblioteki, śledź wydania tutaj.
3. Konfiguracja dla MongoTemplate
3.1. Konfiguracja XML
Zacznijmy od prostej konfiguracji XML dla szablonu Mongo:
<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />
Najpierw musimy zdefiniować ziarno fabryczne odpowiedzialne za tworzenie instancji Mongo.
Następnie musimy faktycznie zdefiniować (i skonfigurować) szablon bean:
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory"/>
</bean>
I na koniec musimy zdefiniować postprocesor, aby przetłumaczyć wszystkie MongoExceptions wrzucony do @Repozytorium klasy z adnotacjami:
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
3.2. Konfiguracja Javy
Stwórzmy teraz podobną konfigurację przy użyciu konfiguracji Java, rozszerzając klasę bazową dla konfiguracji MongoDB 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");
}
}
Pamiętaj, że nie musieliśmy definiować MongoTemplate fasola w poprzedniej konfiguracji, ponieważ jest już zdefiniowana w AbstractMongoClientConfiguration .
Możemy również użyć naszej konfiguracji od podstaw bez rozszerzania 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. Konfiguracja dla MongoRepository
4.1. Konfiguracja XML
Aby skorzystać z niestandardowych repozytoriów (rozszerzenie MongoRepository ), musimy kontynuować konfigurację z sekcji 3.1. i skonfiguruj repozytoria:
<mongo:repositories
base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>
4.2. Konfiguracja Javy
Podobnie, będziemy budować na konfiguracji, którą już stworzyliśmy w sekcji 3.2. i dodaj nową adnotację do miksu:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Utwórz repozytorium
Po konfiguracji musimy utworzyć repozytorium — rozszerzając istniejące MongoRepository interfejs:
public interface UserRepository extends MongoRepository<User, String> {
//
}
Teraz możemy automatycznie połączyć to UserRepository i użyj operacji z MongoRepository lub dodaj niestandardowe operacje.
5. Korzystanie z MongoTemplate
5.1. Wstaw
Zacznijmy od operacji wstawiania oraz od pustej bazy danych:
{
}
Teraz, jeśli wstawimy nowego użytkownika:
User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");
baza danych będzie wyglądać tak:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
5.2. Zapisz – wstaw
zapisz operacja ma semantykę zapisz lub zaktualizuj:jeśli identyfikator jest obecny, wykonuje aktualizację, a jeśli nie, wstawia.
Spójrzmy na pierwszą semantykę — wstawkę.
Oto początkowy stan bazy danych:
{
}
Kiedy teraz zapisujemy nowy użytkownik:
User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");
podmiot zostanie wstawiony do bazy danych:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Albert"
}
Następnie przyjrzymy się tej samej operacji — zapisz — z aktualizacją semantyki.
5.3. Zapisz – zaktualizuj
Spójrzmy teraz na zapisz z semantyką aktualizacji, działającą na istniejącej encji:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"
}
Kiedy zapisujemy istniejącego użytkownika, zaktualizujemy go:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
Baza danych będzie wyglądać tak:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Widzimy, że w tym konkretnym przykładzie zapisz używa semantyki aktualizacji ponieważ używamy obiektu o podanym _id .
5.4. Najpierw zaktualizuj
aktualizacjaNajpierw aktualizuje pierwszy dokument pasujący do zapytania.
Zacznijmy od początkowego stanu bazy danych:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
Kiedy teraz uruchomimy 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);
tylko pierwszy wpis zostanie zaktualizowany:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "James"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
5.5. AktualizujMulti
AktualizujMulti aktualizuje wszystkie dokumenty pasujące do podanego zapytania.
Najpierw stan bazy danych przed wykonaniem updateMulti :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
}
]
Teraz uruchommy updateMulti operacja:
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);
Oba istniejące obiekty zostaną zaktualizowane w bazie danych:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
}
]
5.6. Znajdź i zmodyfikuj
Ta operacja działa jak updateMulti , ale zwraca obiekt przed jego modyfikacją.
Po pierwsze, jest to stan bazy danych przed wywołaniem funkcji findAndModify :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Spójrzmy na rzeczywisty kod operacji:
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);
Zwrócony obiekt użytkownika ma takie same wartości jak stan początkowy w bazie danych.
Jest to jednak nowy stan w bazie danych:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.7. Uwaga
wstawka działa na znajdowaniu i modyfikowaniu innych tworzenia semantyki :jeśli dokument jest dopasowany, zaktualizuj go lub utwórz nowy dokument, łącząc zapytanie i obiekt aktualizacji.
Zacznijmy od początkowego stanu bazy danych:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Teraz uruchommy 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);
Oto stan bazy danych po operacji:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.8. Usuń
Sprawdzimy stan bazy danych przed wywołaniem remove :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Uruchommy teraz usuń :
mongoTemplate.remove(user, "user");
Wynik będzie zgodny z oczekiwaniami:
{
}
6. Korzystanie z MongoRepository
6.1. Wstaw
Najpierw zobaczymy stan bazy danych przed uruchomieniem insert :
{
}
Teraz wstawimy nowego użytkownika:
User user = new User();
user.setName("Jon");
userRepository.insert(user);
A oto stan końcowy bazy danych:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
Zwróć uwagę, jak operacja działa tak samo jak wstaw w MongoTemplate API.
6.2. Zapisz – Wstaw
Podobnie zapisz działa tak samo jak zapisz działanie w MongoTemplate API.
Zacznijmy od przyjrzenia się semantyce wstawiania operacji.
Oto początkowy stan bazy danych:
{
}
Teraz wykonujemy zapis operacja:
User user = new User();
user.setName("Aaron");
userRepository.save(user);
Powoduje to dodanie użytkownika do bazy danych:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Aaron"
}
Jeszcze raz zwróć uwagę, jak zapisywać współpracuje z wstaw semantyki, ponieważ wstawiamy nowy obiekt.
6.3. Zapisz – Aktualizacja
Przyjrzyjmy się teraz tej samej operacji, ale z aktualizacją semantyki.
Najpierw stan bazy danych przed uruchomieniem nowego zapisu :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"81*6
}
Teraz wykonujemy operację:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);
Na koniec stan bazy danych:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Jeszcze raz zwróć uwagę, jak zapisywać współpracuje z aktualizacją semantyki, ponieważ używamy istniejącego obiektu.
6.4. Usuń
Oto stan bazy danych przed wywołaniem delete :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Uruchommy usuń :
userRepository.delete(user);
A oto nasz wynik:
{
}
6.5. Znajdź jeden
Następnie jest to stan bazy danych, gdy findOne nazywa się:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
Wykonajmy teraz findOne :
userRepository.findOne(user.getId())
A wynik zwróci istniejące dane:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
6.6. Istnieje
Stan bazy danych przed wywołaniem istnieje :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Harris"
}
Teraz uruchommy istnieje , co oczywiście zwróci prawdę :
boolean isExists = userRepository.exists(user.getId());
6.7. Znajdź wszystko ZSortuj
Stan bazy danych przed wywołaniem funkcji findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Uruchommy teraz znajdź wszystko zSortuj :
List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
Wynik zostanie posortowany według nazwy w kolejności rosnącej :
[
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
]
6.8. Znajdź wszystko Z stronicowalnym
Stan bazy danych przed wywołaniem funkcji findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Wykonajmy teraz znajdź wszystko z prośbą o paginację:
Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
Wynikowi użytkownicy lista będzie tylko dla jednego użytkownika:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
7. Adnotacje
Na koniec przyjrzyjmy się również prostym adnotacjom, których Spring Data używa do obsługi tych operacji API.
Poziom pola @Id adnotacja może ozdobić dowolny typ, w tym długi i ciąg :
@Id
private String id;
Jeśli wartość @Id pole nie jest puste, jest przechowywane w bazie danych bez zmian; w przeciwnym razie konwerter założy, że chcemy przechowywać ObjectId w bazie danych (albo ObjectId , Ciąg lub BigInteger pracy).
Następnie przyjrzymy się @Document :
@Document
public class User {
//
}
Ta adnotacja po prostu oznacza klasę jako obiekt domeny który musi być utrwalony w bazie danych, wraz z umożliwieniem nam wybrania nazwy kolekcji, która ma zostać użyta.