Рубрики
Без рубрики

Введение в весенние данные MongoDB

Солидное введение в использование MongoDB с весенними данными.

Автор оригинала: baeldung.

1. Обзор

Эта статья будет быстрым и практичным введением в Spring Data MongoDB .

Мы рассмотрим основы, используя как MongoTemplate , так и MongoRepository , используя практические примеры для иллюстрации каждой операции.

Дальнейшее чтение:

Геопространственная поддержка в MongoDB

Тестирование интеграции Spring Boot со встроенным MongoDB

2. MongoTemplate и MongoRepository

MongoTemplate следует стандартному шаблону шаблона весной и предоставляет готовый к работе базовый API для базового механизма сохранения.

Репозиторий следует подходу Spring, ориентированному на данные, и поставляется с более гибкими и сложными операциями API, основанными на хорошо известных шаблонах доступа во всех проектах Spring Data.

Для обоих случаев нам нужно начать с определения зависимости – например, в pom.xml , с Maven:


    org.springframework.data
    spring-data-mongodb
    3.0.3.RELEASE

Чтобы проверить, была ли выпущена какая – либо новая версия библиотеки – отслеживайте выпуски здесь .

3. Конфигурация для MongoTemplate

3.1. Конфигурация XML

Давайте начнем с простой конфигурации XML для шаблона Mongo:


Во-первых, нам нужно определить factorybean, ответственный за создание экземпляров Mongo.

Далее – нам нужно фактически определить (и настроить) компонент шаблона:

 
     

И, наконец, нам нужно определить постпроцессор для перевода любых исключений Mongo , брошенных в @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 bean в предыдущей конфигурации, поскольку он уже определен в AbstractMongoClientConfiguration.

Мы также можем использовать нашу конфигурацию с нуля без расширения Abstract MongoClientConfiguration – следующим образом:

@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. Сохранить – Вставить

Операция save имеет семантику сохранения или обновления: если идентификатор присутствует, он выполняет обновление, если нет-он выполняет вставку.

Давайте рассмотрим первую семантику – вставку; вот начальное состояние базы данных :

{
}

Когда мы сейчас сохраняем нового пользователя:

User user = new User();
user.setName("Albert"); 
mongoTemplate.save(user, "user");

Объект будет вставлен в базу данных:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Albert"
}

Далее мы рассмотрим ту же операцию – save – с семантикой обновления.

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

update First обновляет самый первый документ, соответствующий запросу.

Давайте начнем с начального состояния базы данных:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Alex"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "com.baeldung.model.User",
        "name" : "Alex"
    }
]

Когда мы сейчас запустим обновление Первым :

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

Update Multi обновляет весь документ, соответствующий данному запросу .

Во – первых- вот состояние базы данных перед выполнением updateMulti :

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "com.baeldung.model.User",
        "name" : "Eugen"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "com.baeldung.model.User",
        "name" : "Eugen"
    }
]

Теперь давайте запустим операцию update Multi :

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. Найти и изменить

Эта операция работает как update Multi , но она возвращает объект до того, как он был изменен .

Во – первых- состояние базы данных перед вызовом 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);

Возвращаемый объект user имеет те же значения, что и начальное состояние в базе данных.

Однако новое состояние в базе данных является:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Nick"
}

5.7. Upsert

upsert работает с семантикой findandmodify 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"
}

Теперь давайте запустим удалить :

mongoTemplate.remove(user, "user");

Результат будет таким, как и ожидалось:

{
}

6. Использование MongoRepository

6.1. Вставить

Первый – состояние базы данных перед запуском insert:

{
}

Теперь, когда мы вставляем нового пользователя:

User user = new User();
user.setName("Jon");
userRepository.insert(user);

Вот конечное состояние базы данных:

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "com.baeldung.model.User",
    "name" : "Jon"
}

Обратите внимание, что операция работает так же, как insert в MongoTemplate API.

6.2. Сохранить – Вставить

Аналогично – save работает так же, как операция save в MongoTemplate API.

Давайте начнем с рассмотрения семантики вставки операции; вот начальное состояние базы данных:

{
}

Теперь – мы выполняем операцию save :

User user = new User();
user.setName("Aaron");
userRepository.save(user);

Это приводит к тому, что пользователь добавляется в базу данных:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "com.baeldung.model.User",
    "name" : "Aaron"
}

Еще раз обратите внимание, как в этом примере save работает с семантикой insert , поскольку мы вставляем новый объект.

6.3. Сохранить – Обновить

Давайте теперь рассмотрим ту же операцию, но с семантикой обновления .

Во – первых- вот состояние базы данных перед запуском нового save:

{
    "_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"
}

Еще раз обратите внимание, как в этом примере save работает с update семантикой, поскольку мы используем существующий объект.

6.4. Исключить

Состояние базы данных перед вызовом delete :

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Benn"
}

Давайте запустим delete :

userRepository.delete(user);

Результат будет просто:

{
}

6.5. findOne

Состояние базы данных при вызове find One :

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Chris"
}

Теперь давайте выполним команду find One :

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"
}

Теперь давайте запустим существует :

boolean isExists = userRepository.exists(user.getId());

Что, конечно, вернет true .

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 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 page = userRepository.findAll(pageableRequest);
List users = pages.getContent();

В результирующем списке users будет только один пользователь:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "com.baeldung.model.User",
    "name" : "Brendan"
}

7. Аннотации

Наконец, давайте также рассмотрим простые аннотации, которые Spring Data использует для управления этими операциями API.

@Id
private String id;

Аннотацию уровня поля @Id можно украсить любым типом, включая long и string .

Если значение поля @Id не равно нулю, оно хранится в базе данных как есть; в противном случае конвертер предположит, что вы хотите сохранить ObjectId в базе данных (либо ObjectId, String или BigInteger work).

Далее – @Document :

@Document
public class User {
    //
}

Эта аннотация просто помечает класс как объект домена , который должен быть сохранен в базе данных, а также позволяет нам выбрать имя используемой коллекции.

8. Заключение

Эта статья была быстрым, но исчерпывающим введением в использование MongoDB с данными Spring, как через MongoTemplate API, так и с использованием MongoRepository .

Реализацию всех этих примеров и фрагментов кода можно найти на Github .