MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Въведение в Spring Data MongoDB

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 {
    //
}

Тази анотация просто маркира клас като обект на домейн която трябва да бъде запазена в базата данни, заедно с това да ни позволи да изберем името на колекцията, която да се използва.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. mongodb - Намерете документ с най-близката целочислена стойност

  2. Mongoose -- Име на колекцията принудително

  3. Групирайте и пребройте с условие

  4. Мониторинг на Percona сървър за MongoDB – ключови показатели

  5. Как да премахнете дублиращи се записи от масив?