Автоматически сгенерированное поле для MongoDB с использованием Spring Boot

Автоматически сгенерированное поле для MongoDB с использованием Spring Boot

1. обзор

В этом руководстве мы узнаем, как реализовать последовательное автоматически сгенерированное поле для MongoDB в Spring Boot.

When we’re using MongoDB as the database for a Spring Boot application, we can’t use @GeneratedValue annotation in our models as it’s not available. Следовательно, нам нужен метод, обеспечивающий тот же эффект, что и при использовании JPA и базы данных SQL.

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

2. зависимости

Давайте добавим к нашемуpom.xml следующие пружинные стартеры:


    
        org.springframework.boot
        spring-boot-starter-web
        2.1.0.RELEASE
    
    
        org.springframework.boot
        spring-boot-starter-data-mongodb
        2.1.0.RELEASE
    

Последней версией зависимостей управляетspring-boot-starter-parent.

3. Коллекции

Как обсуждалось в обзоре, мы создадим коллекцию, в которой будет храниться автоматически увеличивающаяся последовательность для других коллекций. Мы назовем эту коллекциюdatabase_sequences. . Ее можно создать с помощью оболочкиmongo или MongoDB Compass. Создадим соответствующий класс модели:

@Document(collection = "database_sequences")
public class DatabaseSequence {

    @Id
    private String id;

    private long seq;

    //getters and setters omitted
}

Затем давайте создадим коллекциюusers и соответствующий объект модели, в котором будут храниться сведения о людях, использующих нашу систему:

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

    @Transient
    public static final String SEQUENCE_NAME = "users_sequence";

    @Id
    private long id;

    private String email;

    //getters and setters omitted
}

В моделиUser, созданной выше, мы добавили статическое полеSEQUENCE_NAME,, которое является уникальной ссылкой на автоматически увеличивающуюся последовательность для коллекцииusers.

Мы также аннотируем его@Transient, чтобы предотвратить его сохранение вместе с другими свойствами модели.

4. Создание новой записи

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

Давайте создадимSequenceGeneratorService сgenerateSequence():

public long generateSequence(String seqName) {
    DatabaseSequence counter = mongoOperations.findAndModify(query(where("_id").is(seqName)),
      new Update().inc("seq",1), options().returnNew(true).upsert(true),
      DatabaseSequence.class);
    return !Objects.isNull(counter) ? counter.getSeq() : 1;
}

Теперь мы можем использоватьgenerateSequence() при создании новой записи:

User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
user.setEmail("[email protected]");
userRepository.save(user);

Чтобы перечислить всех пользователей, мы будем использоватьUserRepository:

List storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);

Как и сейчас, мы должны устанавливать поле id каждый раз, когда мы создаем новый экземпляр нашей модели. Мы можем обойти этот процесс, создав прослушиватель событий жизненного цикла Spring Data MongoDB.

Для этого мы создадимUserModelListener, который расширяетAbstractMongoEventListener<User>, а затем переопределимonBeforeConvert():

@Override
public void onBeforeConvert(BeforeConvertEvent event) {
    if (event.getSource().getId() < 1) {
        event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
    }
}

Теперь каждый раз, когда мы сохраняем новыйUser,,id будет устанавливаться автоматически.

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

В заключение мы увидели, как генерировать последовательные автоматически увеличивающиеся значения для поля id и моделировать то же поведение, что и в базах данных SQL.

Hibernate использует аналогичный метод для генерации автоинкрементных значений по умолчанию.

Как обычно, доступен полный исходный кодover on Github.