1. Прегледа
В този урок ще научим как да внедрим последователно, автоматично генерирано поле за MongoDB в Spring Boot.
Когато използваме MongoDB като база данни за Spring Boot приложение, не можем да използваме @GeneratedValue анотация в нашите модели, тъй като не е налична. Следователно имаме нужда от метод, който да произвежда същия ефект, който ще имаме, ако използваме JPA и SQL база данни.
Общото решение на този проблем е просто. Ще създадем колекция (таблица), която ще съхранява генерираната последователност за други колекции. По време на създаването на нов запис ще го използваме, за да извлечем следващата стойност.
2. Зависимости
Нека добавим следните стартери за пружинно зареждане към нашия pom.xml :
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<versionId>2.2.2.RELEASE</versionId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<versionId>2.2.2.RELEASE</versionId>
</dependency>
</dependencies>
Най-новата версия за зависимостите се управлява от spring-boot-starter-parent .
3. Колекциите
Както беше обсъдено в прегледа, ще създадем колекция, която ще съхранява автоматично увеличената последователност за други колекции. Ще наречем тази колекция database_sequences. Може да се създаде с помощта на mongo shell или MongoDB Compass. Нека създадем съответен моделен клас:
@Document(collection = "database_sequences")
public class DatabaseSequence {
@Id
private String id;
private long seq;
//getters and setters omitted
}
След това нека създадем потребители колекция и съответен модел обект, който ще съхранява подробностите за хората, които използват нашата система:
@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
}
В Потребител модел, създаден по-горе, добавихме статично поле SEQUENCE_NAME, което е уникална препратка към автоматично увеличената последователност за потребителите колекция.
Ние също го анотираме с @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<User> storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);
Както е сега, трябва да задаваме полето id всеки път, когато създаваме нов екземпляр на нашия модел. Можем да заобиколим този процес, като създадем слушател за събития от жизнения цикъл на Spring Data MongoDB.
За да направим това, ще създадем UserModelListener който разширява AbstractMongoEventListener
@Override
public void onBeforeConvert(BeforeConvertEvent<User> event) {
if (event.getSource().getId() < 1) {
event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
}
}
Сега всеки път, когато запазваме нов Потребител, идентификаторът ще бъде зададен автоматично.