1. Прегледа
Тази статия ще бъде бързо и практично въведение в Spring Data MongoDB.
Ще разгледаме основите, използвайки и двата MongoTemplate както и MongoRepository , с практически примери за илюстриране на всяка операция.
Допълнително четене:
Геопространствена поддръжка в MongoDB
Вижте как да съхранявате, индексирате и търсите геопространствени данни с MongoDBПрочетете повече →Пролетно стартиране на интеграционно тестване с вградена MongoDB
Научете как да използвате вграденото решение MongoDB на Flapdoodle заедно с Spring Boot, за да изпълнявате гладко тестове за интеграция на MongoDB. Прочетете повече →2. MongoTemplate и MongoRepository
MongoTemplate следва стандартния шаблон на модела в Spring и предоставя готов за работа основен API към основния механизъм за постоянство.
Хранилище следва подхода, ориентиран към Spring Data, и се предлага с по-гъвкави и сложни операции на API, базирани на добре познатите модели на достъп във всички проекти на Spring Data.
И за двете трябва да започнем с дефиниране на зависимостта – например в pom.xml , с Maven:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.0.3.RELEASE</version>
</dependency>
За да проверите дали е пусната нова версия на библиотеката, проследете изданията тук.
3. Конфигурация за MongoTemplate
3.1. XML конфигурацията
Нека започнем с простата XML конфигурация за шаблона Mongo:
<mongo:mongo-client id="mongoClient" host="localhost" />
<mongo:db-factory id="mongoDbFactory" dbname="test" mongo-client-ref="mongoClient" />
Първо трябва да дефинираме фабричния бийн, отговорен за създаването на екземпляри на Mongo.
След това трябва действително да дефинираме (и да конфигурираме) шаблонния bean:
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory"/>
</bean>
И накрая, трябва да дефинираме постпроцесор, който да преведе всички MongoExceptions хвърлен в @Repository анотирани класове:
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
3.2. Конфигурация на Javaта
Нека сега създадем подобна конфигурация с помощта на Java config, като разширим базовия клас за конфигурацията на 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");
}
}
Имайте предвид, че не е необходимо да дефинираме MongoTemplate bean в предишната конфигурация, тъй като вече е дефиниран в AbstractMongoClientConfiguration .
Можем също да използваме нашата конфигурация от нулата, без да разширяваме 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. Конфигурация за MongoRepository
4.1. XML конфигурацията
За да използвате персонализирани хранилища (разширяване на MongoRepository ), трябва да продължим конфигурацията от раздел 3.1. и настройте хранилищата:
<mongo:repositories
base-package="com.baeldung.repository" mongo-template-ref="mongoTemplate"/>
4.2. Конфигурация на Javaта
По подобен начин ще надградим конфигурацията, която вече създадохме в раздел 3.2. и добавете нова анотация към микса:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Създайте хранилищета
След конфигурацията трябва да създадем хранилище – разширяване на съществуващото MongoRepository интерфейс:
public interface UserRepository extends MongoRepository<User, String> {
//
}
Сега можем автоматично да свържем това UserRepository и използвайте операции от MongoRepository или добавете персонализирани операции.
5. Използване на MongoTemplate
5.1. Вмъкване
Нека започнем с операцията вмъкване, както и с празна база данни:
{
}
Сега, ако вмъкнем нов потребител:
User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");
базата данни ще изглежда така:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
5.2. Запазване – Вмъкване
Сзапазване операцията има семантика за запазване или актуализиране:ако има идентификатор, тя извършва актуализация, а ако не, прави вмъкване.
Нека разгледаме първата семантика — вмъкването.
Ето първоначалното състояние на базата данни:
{
}
Когато сега запазим нов потребител:
User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");
обектът ще бъде вмъкнат в базата данни:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Albert"
}
След това ще разгледаме същата операция — запазване — със семантика за актуализиране.
5.3. Запазване – Актуализиране
Нека сега да разгледаме запазване със семантика за актуализиране, работещ върху съществуващ обект:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"
}
Когато запазим съществуващ потребител, ние ще го актуализираме:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");
Базата данни ще изглежда така:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Можем да видим, че в този конкретен пример save използва семантиката на актуализация защото използваме обект с даден _id .
5.4. UpdateFirst
updateFirst актуализира първия документ, който съответства на заявката.
Нека започнем с първоначалното състояние на базата данни:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
Когато стартираме 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);
само първият запис ще бъде актуализиран:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "James"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Alex"
}
]
5.5. UpdateMulti
UpdateMulti актуализира всички документи, които отговарят на дадената заявка.
Първо, ето състоянието на базата данни, преди да направите updateMulti :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Eugen"
}
]
Сега нека стартираме updateMulti операция:
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);
И двата съществуващи обекта ще бъдат актуализирани в базата данни:
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
"_class" : "com.baeldung.model.User",
"name" : "Victor"
}
]
5.6. FindAndModify
Тази операция работи като updateMulti , но връща обекта, преди да е бил променен.
Първо, това е състоянието на базата данни, преди да извикате findAndModify :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Нека разгледаме действителния код на операцията:
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);
Върнатият потребителски обект има същите стойности като първоначалното състояние в базата данни.
Това обаче е новото състояние в базата данни:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.7. Нагоре
Разстроен работи върху намерете и модифицирайте else create семантика :ако документът съответства, актуализирайте го или създайте нов документ, като комбинирате заявката и обекта за актуализиране.
Нека започнем с първоначалното състояние на базата данни:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Markus"
}
Сега нека стартираме 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);
Ето състоянието на базата данни след операцията:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Nick"
}
5.8. Премахване
Ще разгледаме състоянието на базата данни, преди да извикаме remove :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Нека сега стартираме remove :
mongoTemplate.remove(user, "user");
Резултатът ще бъде както се очаква:
{
}
6. Използване на MongoRepository
6.1. Вмъкване
Първо, ще видим състоянието на базата данни, преди да стартираме вмъкването :
{
}
Сега ще вмъкнем нов потребител:
User user = new User();
user.setName("Jon");
userRepository.insert(user);
А ето и крайното състояние на базата данни:
{
"_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
"_class" : "com.baeldung.model.User",
"name" : "Jon"
}
Обърнете внимание как операцията работи по същия начин като вмъкването в MongoTemplate API.
6.2. Запазване – Вмъкване
По същия начин запазете работи по същия начин като запазването операция в MongoTemplate API.
Нека започнем, като разгледаме семантиката на вмъкването на операцията.
Ето първоначалното състояние на базата данни:
{
}
Сега изпълняваме save операция:
User user = new User();
user.setName("Aaron");
userRepository.save(user);
Това води до добавяне на потребителя към базата данни:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Aaron"
}
Отбележете отново как запазете работи с вмъкване семантика, защото вмъкваме нов обект.
6.3. Запазване – Актуализация
Нека сега да разгледаме същата операция, но с актуализация на семантиката
Първо, ето състоянието на базата данни, преди да стартирате новото запазване :
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jack"81*6
}
Сега изпълняваме операцията:
user = mongoTemplate.findOne(
Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);
И накрая, ето състоянието на базата данни:
{
"_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
"_class" : "com.baeldung.model.User",
"name" : "Jim"
}
Отбележете отново как запазете работи с актуализация семантика, защото използваме съществуващ обект.
6.4. Изтриване
Ето състоянието на базата данни, преди да извикате delete :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Benn"
}
Нека стартираме delete :
userRepository.delete(user);
И ето нашия резултат:
{
}
6.5. FindOne
След това това е състоянието на базата данни, когато findOne се нарича:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
Нека сега изпълним findOne :
userRepository.findOne(user.getId())
И резултатът ще върне съществуващите данни:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Chris"
}
6.6. Съществува
Състоянието на базата данни преди извикване съществува :
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Harris"
}
Сега нека стартираме exists , което разбира се ще върне true :
boolean isExists = userRepository.exists(user.getId());
6.7. Намери всички С Сортиране
Състоянието на базата данни преди извикване на findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Нека сега стартираме findAll с Сортиране :
List<User> users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
Резултатът ще бъде сортиран по име във възходящ ред :
[
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
},
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
]
6.8. Намери всички С Страница
Състоянието на базата данни преди извикване на findAll :
[
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
},
{
"_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Adam"
}
]
Нека сега изпълним findAll със заявка за пагинация:
Pageable pageableRequest = PageRequest.of(0, 1);
Page<User> page = userRepository.findAll(pageableRequest);
List<User> users = pages.getContent();
Получените потребители списъкът ще съдържа само един потребител:
{
"_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
"_class" : "com.baeldung.model.User",
"name" : "Brendan"
}
7. Анотациите
И накрая, нека разгледаме и простите пояснения, които Spring Data използва за управление на тези операции на API.
Нивото на полето @Id анотацията може да украсява всякакъв тип, включително дълга и низ :
@Id
private String id;
Ако стойността на @Id полето не е нула, то се съхранява в базата данни както е; в противен случай конверторът ще приеме, че искаме да съхраняваме ObjectId в базата данни (или ObjectId , Низ или BigInteger работа).
След това ще разгледаме @Document :
@Document
public class User {
//
}
Тази анотация просто маркира клас като обект на домейн която трябва да бъде запазена в базата данни, заедно с това да ни позволи да изберем името на колекцията, която да се използва.