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

Как создавать пользовательские запросы с помощью Spring Data Reactive MongoDB

Этот пост знакомит читателей с реализацией методов обновления с помощью реактивного MongoDB для Spring Data…. Помечено как java, учебное пособие, база данных, mongodb.

Этот пост знакомит читателей с реализацией методов обновления с помощью реактивного MongoDB для Spring Data. В нем основное внимание уделяется основным принципам расширения Реактивного репозитория Mongo с пользовательской функциональностью и приводятся четыре конкретных примера.

Начало работы с ReactiveMongo для весенних данных

Из коробки, Spring предоставляет нам репозитории, которые предлагают базовую функциональность CRUD, например, вставку, удаление, обновление и извлечение данных. В случае реактивного доступа к MongoDB мы говорим о Реактивном репозитории Mongo интерфейс, который фиксирует тип домена для управления, а также тип идентификатора типа домена. Есть два способа расширить его функциональность:

  • Используйте производные методы запроса , которые генерируются из пользовательских сигнатур методов, которые вы объявляете в интерфейсе, подобном Найти первое имя – это выходит за рамки данного поста.
  • Создайте пользовательскую реализацию и объедините ее с Реактивным репозиторием Mongo – это то, что мы сделаем в этой статье.

Для начала вам необходимо иметь reactive MongoDB starter, определенный с помощью вашего инструмента управления зависимостями. Если вы используете Maven, добавьте следующую зависимость в свой pom. :


    
    
        org.springframework.boot
        spring-boot-starter-data-mongodb-reactive
    

Давайте создадим пользовательскую сущность для использования в нашем примере. Давайте сделаем традиционный пример – управление пользователями . Этот код объявляет объект User , который мы будем использовать в этом посте:

@Value @AllArgsConstructor
@Document(collection = "users")
public class User {

    @NonFinal @Id String userId;
    String email;
    String password;
    List roles;
}

Следующий шаг – объявить репозиторий, который расширяет Реактивный репозиторий Mongo/| Для целей руководства давайте создадим обычный пользовательский репозиторий:

@Repository
public interface UserRepository extends ReactiveMongoRepository {}

Этот интерфейс предоставит нам базовую функциональность CRUD для Пользователь юридические лица, в том числе:

  • Сохранить
  • Извлекать по идентификатору
  • Обновление
  • Извлеките все
  • Удалять

Это, однако, не включает пользовательские функции, которые нам могут понадобиться с помощью Пользователь объекты. Например, нам может потребоваться обновить не полную запись записи, а только определенные поля, такие как пароль . Таким же образом нам может потребоваться обработать изменения для вложенных объектов/массивов объекта. Для этого мы не можем использовать производные методы запросов, но мы должны объявить пользовательский репозиторий. Давайте посмотрим, как это сделать.

Как расширить репозиторий ReactiveMongo

Процесс расширения репозитория Spring reactive Mongo пользовательской функциональностью состоит из 3 шагов:

  1. Создайте интерфейс, который определяет пользовательские методы управления данными, например Пользовательский пользовательский репозиторий
  2. Предоставьте реализацию, используя Шаблон ReactiveMongo для доступа к источнику данных. Имя интерфейса реализации должно иметь Impl постфикс, как Репозиторий пользовательских пользователей impl
  3. Расширьте основной репозиторий с помощью пользовательского интерфейса репозитория. Например, UserRepository расширяет репозиторий ReactiveMongo, CustomUserRepository

Давайте приведем практический пример. Мы уже упоминали Пользовательское хранилище в качестве точки входа для операций доступа к данным. Мы будем использовать этот репозиторий в службах для обработки доступа к источникам данных. Однако Spring создаст только реализации для операций CRUD, а для обновлений пользовательских методов нам нужно будет предоставить собственные реализации. Но это не ракетостроение с Spring.

Первое, что нужно сделать, это создать пользовательский интерфейс для объявления наших собственных методов обновления. Давайте назовем это Пользовательский Пользовательский репозиторий :

public interface CustomUserRepository {

    Mono changePassword (String userId, String newPassword);

    Mono addNewRole (String userId, Role role);

    Mono removeRole (String userId, String permission);

    Mono hasPermission (String userId, String permission);
}

Затем, на шаге 2, нам нужно предоставить пользовательскую реализацию . Это тот шаг, на котором нам нужно будет выполнить большую часть работы. Позже мы рассмотрим каждый метод отдельно, а пока предоставим необходимую конфигурацию. Что нам нужно сделать:

  • Предоставьте зависимость типа Шаблон ReactiveMongo . Мы будем использовать его для доступа к базовому источнику данных.
  • Добавьте конструктор, в который Spring введет необходимый компонент. Кроме того, аннотируйте конструктор с помощью @Автоматическое подключение

Взгляните на приведенный ниже фрагмент кода:

public class CustomUserRepositoryImpl implements CustomUserRepository {

    private final ReactiveMongoTemplate mongoTemplate;

    @Autowired
    public CustomUserRepositoryImpl(ReactiveMongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    @Override
    public Mono changePassword(String userId, String newPassword) {
        return null;
    }

    @Override
    public Mono addNewRole(String userId, Role role) {
        return null;
    }

    @Override
    public Mono removeRole(String userId, String permission) {
        return null;
    }

    @Override
    public Mono hasPermission(String userId, String permission) {
        return null;
    }

}

Наконец, нам нужно дать Spring знать, что мы хотим использовать этот репозиторий наряду со встроенным. Для этого расширьте UserRepository с помощью Пользовательского пользовательского репозитория интерфейс, подобный этому:

public interface UserRepository extends ReactiveMongoRepository, CustomUserRepository {
    //...
}

Итак, теперь мы готовы приступить к реализации пользовательских методов обновления.

Реализовать пользовательские функции обновления

В этом разделе мы рассмотрим, как реализовать пользовательские методы обновлений с помощью реактивного MongoDB в Spring. Каждый метод описан отдельно.

Обновить поле объекта

Одним из наиболее распространенных требований является изменение значения поля объекта. В нашем примере мы используем поле подтверждено для сохранения того, подтвердил ли пользователь свою учетную запись или нет. Конечно, в нашем примере мы концентрируемся только на логике базы данных и не будем обрабатывать рабочий процесс подтверждения, поэтому, пожалуйста, предположим, что наш UserService сделал все правильно и теперь использует репозиторий для обновления статуса пользователя.

Взгляните на приведенный ниже фрагмент кода:

@Override
public Mono changePassword(String userId, String newPassword) {
    // step 1
    Query query = new Query(Criteria.where("userId").is(userId)); 

    // step 2
    Update update = new Update().set("password", newPassword);

    // step 3
    return mongoTemplate.findAndModify(query, update, User.class);
}

Давайте рассмотрим, что мы здесь делаем:

  1. Создайте объект query , который находит конкретного пользователя с определенным идентификатором пользователя
  2. Создайте объект update , чтобы изменить значение поля confirmed на true . Для этого , используйте set() метод, который принимает в качестве первого аргумента имя поля (ключ), а в качестве второго – новое значение
  3. Наконец, выполните обновление с помощью MongoTemplate object. Метод findAndModify используется для применения предоставленного обновления к документам, которые соответствуют определенным критериям.

Обратите внимание, что в принципе, поток такой же, если мы используем “традиционный” синхронный Spring MongoDB. Единственное отличие заключается в типе возвращаемого значения – вместо равнина Пользователь объект, реактивный репозиторий возвращает Mono .

Добавление во вложенный массив

Еще одна широко распространенная операция, которую вам может потребоваться выполнить в ваших приложениях, – это добавление нового объекта во вложенный массив. Допустим, мы хотим добавить новую роль для конкретного пользователя. В нашем примере мы храним разрешения во вложенном списке роли .

Опять же, мы не фокусируемся на том, как на самом деле осуществляется управление разрешениями, и предполагаем, что Служба пользователя делает все по мере необходимости. Вот реализация:

@Override
public Mono addNewRole(String userId, Role role) {
    // step 1
    Query query = new Query(Criteria.where("userId").is(userId));

    // step 2
    Update update = new Update().addToSet("roles", role);

    // step 3
    return mongoTemplate.findAndModify(query, update, User.class);
}

В принципе, шаги те же самые. Единственное изменение – это объект Update . Мы используем здесь addToSet метод, который принимает имя вложенного массива – роли и объект для вставки в него.

Существует другой подход к добавлению объекта во вложенную коллекцию – push :

// ..
Update updateWithPush = new Update().push("roles", role);

Разница между этими двумя методами заключается в следующем:

  • Метод addToSet не допускает дублирования и вставляет объект только , если коллекция его еще не содержит.
  • метод push допускает дублирование и может вставлять один и тот же объект несколько раз

Удалить из вложенного массива

Как будто мы добавляем что-то во вложенную коллекцию, нам может потребоваться удалить это. Как мы делаем в наших примерах управления ролями, мы можем захотеть отозвать у пользователя предоставленные права доступа. Чтобы сделать это, нам действительно нужно удалить элемент из вложенной коллекции. Взгляните на приведенный ниже фрагмент кода:

@Override
public Mono removeRole(String userId, String permission) {
    // step 1
    Query query = new Query(Criteria.where("userId").is(userId));

    // step 2
    Update update = new Update().pull("roles",
         new BasicDBObject("permission", permission));

    // step 3
    return mongoTemplate.findAndModify(query, update, User.class);
}

Объект обновления использует метод pull для удаления роли с заданным разрешением значением. Мы предполагаем, что разрешения уникальны, но в реальной жизни лучше использовать некоторые внутренние уникальные идентификаторы для управления вложенными объектами. Мы можем разделить этот шаг на две части:

  1. оператор pull принимает в качестве первого аргумента имя вложенной коллекции
  2. Второй аргумент – это BasicDBObject , который определяет критерий того, какую роль мы хотим удалить. В нашем случае мы используем разрешение поле, чтобы указать его

Запрос по полю вложенного объекта

Мы уже упоминали, что Spring помогает нам выполнять запросы с помощью производных методов запросов, как findByName . Хотя это будет работать с полями объекта, но что, если мы хотим выполнить запрос с помощью вложенного объекта?

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

Давайте посмотрим, как мы можем решить эту задачу:

@Override
// 1
public Mono hasPermission(String userId, String permission) {

    // 2
    Query query = new Query(Criteria.where("userId").is(userId))
            .addCriteria(Criteria.where("roles.permission").is(permission)); //3

    // 4
    return mongoTemplate.exists(query, User.class);
}

Отпускай шаг за шагом:

  1. В отличие от предыдущих методов, этот метод возвращает Mono результат, который обертывает логическое значение, указывающее на наличие/отсутствие желаемого разрешения.
  2. Нам нужно объединить два критерия, потому что мы ищем конкретного пользователя с определенным разрешением. Запрос object предлагает плавный интерфейс, и мы можем связать критерии с помощью метода add Criteria .
  3. Мы создаем объект запроса, который ищет объект role внутри массива roles с необходимым значением permission .
  4. Наконец, мы вызываем метод exists , который принимает запрос и проверяет наличие запрошенных данных

Исходный код

Вот как вы можете создавать пользовательские запросы на обновление, используя реактивный MongoDB с помощью Весна . Вы можете найти полный исходный код в этом репозитории Github .

Оригинал: “https://dev.to/iuriimednikov/how-to-build-custom-queries-with-spring-data-reactive-mongodb-1802”