1. Общ преглед
Тази статия ще бъде кратко и практично въведение в Spring Data MongoDB .
Ще разгледаме основите, използвайки както MongoTemplate, така и MongoRepository, използвайки практически примери, за да илюстрираме всяка операция.
2. MongoTemplate и MongoRepository
В MongoTemplate следва стандартната модел шаблон през пролетта и осигурява готови да отидете, основно API до основната постоянство двигателя.
Хранилището следва подхода, ориентиран към Spring Data, и предлага по-гъвкави и сложни API операции, базирани на добре познатите модели за достъп във всички проекти на Spring Data.
И за двете трябва да започнем с дефиниране на зависимостта - например в pom.xml , с Maven:
org.springframework.data spring-data-mongodb 3.0.3.RELEASE
За да проверите дали е издадена нова версия на библиотеката - проследете изданията тук.
3. Конфигурация за MongoTemplate
3.1. XML конфигурация
Нека започнем с простата XML конфигурация за шаблона Mongo:
Първо, трябва да определим фабричния боб, отговорен за създаването на екземпляри на Монго.
След това - трябва действително да дефинираме (и конфигурираме) шаблона:
И накрая, трябва да дефинираме постпроцесор, който да превежда всички MongoExceptions, хвърлени в @Repository анотирани класове:
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 в предишната конфигурация, тъй като той вече е дефиниран в 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 и да настроим хранилищата:
4.2. Конфигурация на Java
По същия начин ще надградим върху конфигурацията, която вече сме създали в раздел 3.2, и ще добавим нова анотация в микса:
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
4.3. Създайте хранилището
Сега, след конфигурирането, трябва да създадем хранилище - разширяване на съществуващия интерфейс MongoRepository :
public interface UserRepository extends MongoRepository { // }
Сега можем автоматично да свързваме този 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. Запазване - Актуализиране
Нека сега разгледаме save с семантика за актуализация, работеща върху съществуващ обект:
{ "_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 използва семантиката на update , защото използваме обект с даден _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
This operation works like updateMulti, but it returns the object before it was modified.
First – the state of the database before calling findAndModify:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Markus" }
Let's look at the actual operation code:
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);
The returned user object has the same values as the initial state in the database.
However, the new state in the database is:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Nick" }
5.7. Upsert
The upsert works operate on the find and modify else create semantics: if the document is matched, update it, else create a new document by combining the query and update object.
Let's start with the initial state of the database:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Markus" }
Now – let's run the 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);
Here's the state of the database after the operation:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Nick" }
5.8. Remove
The state of the database before calling remove:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Benn" }
Let's now run remove:
mongoTemplate.remove(user, "user");
The result will be as expected:
{ }
6. Using MongoRepository
6.1. Insert
First – the state of the database before running the insert:
{ }
Now, when we insert a new user:
User user = new User(); user.setName("Jon"); userRepository.insert(user);
Here's the end state of the database:
{ "_id" : ObjectId("55b4fda5830b550a8c2ca25a"), "_class" : "com.baeldung.model.User", "name" : "Jon" }
Note how the operation works the same as the insert in the MongoTemplate API.
6.2. Save – Insert
Similarly – save works the same as the save operation in the MongoTemplate API.
Let's start by looking at the insert semantics of the operation; here's the initial state of the database:
{ }
Now – we execute the save operation:
User user = new User(); user.setName("Aaron"); userRepository.save(user);
This results in the user being added to the database:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Aaron" }
Note again how, in this example, save works with insert semantics, because we are inserting a new object.
6.3. Save – Update
Let's now look at the same operation but with update semantics.
First – here's the state of the database before running the new save:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Jack"81*6 }
Now – we execute the operation:
user = mongoTemplate.findOne( Query.query(Criteria.where("name").is("Jack")), User.class); user.setName("Jim"); userRepository.save(user);
Finally, here is the state of the database:
{ "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"), "_class" : "com.baeldung.model.User", "name" : "Jim" }
Note again how, in this example, save works with update semantics, because we are using an existing object.
6.4. Delete
The state of the database before calling delete:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Benn" }
Let's run delete:
userRepository.delete(user);
The result will simply be:
{ }
6.5. FindOne
The state of the database when findOne is called:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Chris" }
Let's now execute the findOne:
userRepository.findOne(user.getId())
The result which will return the existing data:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Chris" }
6.6. Exists
The state of the database before calling exists:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Harris" }
Now, let's run exists:
boolean isExists = userRepository.exists(user.getId());
Which of course will return true.
6.7. FindAll W ith Sort
The state of the database before calling findAll:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" }, { "_id" : ObjectId("67b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Adam" } ]
Let's now run findAll with Sort:
List users = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name"));
The result will be sorted by name in ascending order:
[ { "_id" : ObjectId("67b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Adam" }, { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" } ]
6.8. FindAll W ith Pageable
The state of the database before calling findAll:
[ { "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" }, { "_id" : ObjectId("67b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Adam" } ]
Let's now execute findAll with a pagination request:
Pageable pageableRequest = PageRequest.of(0, 1); Page page = userRepository.findAll(pageableRequest); List users = pages.getContent();
The resulting users list will be only one user:
{ "_id" : ObjectId("55b5ffa5511fee0e45ed614b"), "_class" : "com.baeldung.model.User", "name" : "Brendan" }
7. Annotations
Finally, let's also go over the simple annotations that Spring Data uses to drive these API operations.
@Id private String id;
The field level @Id annotation can decorate any type, including long and string.
If the value of the @Id field is not null, it's stored in the database as-is; otherwise, the converter will assume you want to store an ObjectId in the database (either ObjectId, String or BigInteger work).
Next – @Document:
@Document public class User { // }
This annotation simply marks a class as being a domain object that needs to be persisted to the database, along with allowing us to choose the name of the collection to be used.
8. Conclusion
This article was a quick but comprehensive introduction to using MongoDB with Spring Data, both via the MongoTemplate API as well as making use of MongoRepository.
The implementation of all these examples and code snippets can be found over on Github.