Auto-Generated Field MongoDB
NỘI DUNG BÀI VIẾT
Tổng quát
Trong hướng dẫn này, chúng ta sẽ tìm hiểu cách implement một sequential, auto-generated field cho MongoDB trong Spring Boot.
Khi chúng ta đang sử dụng MongoDB làm cơ sở dữ liệu cho ứng dụng Spring Boot, chúng ta không thể sử dụng annotation @GeneratedValue trong các model của mình vì nó không khả dụng. Do đó, chúng ta cần một phương pháp để tạo generate value giống như chúng ta đang sử dụng JPA và cơ sở dữ liệu SQL.
Tổng hợp 200+ tài liệu, sách, bài thực hành, video hướng dẫn lập trình… từ cơ bản đến nâng cao
Giải pháp cho vấn đề này rất đơn giản, tôi sẽ tạo ra 1 collection (table) sẽ lưu trữ trình tự đã tạo ra các collection khác. Trong quá trình tạo 1 bản ghi mới, chúng tôi sẽ sử dụng nó để tạo giá trị tiếp theo.
Dependency
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>
Code language: HTML, XML (xml)
Phiên bản mới nhất cho các phần dependency được quản lý bởi spring-boot-starter-parent.
Collections
Như đã thảo luận trong phần tổng quan, tôi sẽ tạo ra một collection sẽ lưu trữ trình tự tăng dần tự động cho các collection khác. Tôi sẽ gọi collection này là database_sequences. Nó có thể được tạo bằng cách sử dụng mongo shell hoặc MongoDB Compass. Hãy tạo một class model tương ứng:
@Document(collection = "database_sequences")
public class DatabaseSequence {
@Id
private String id;
private long seq;
//getters and setters omitted
}
Code language: PHP (php)
Sau đó, hãy tạo một tập hợp User và một object model tương ứng, sẽ lưu trữ thông tin chi tiết về những người đang sử dụng hệ thống của tôi:
@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
}
Code language: PHP (php)
Trong model User đã tạo ở trên, chúng tôi đã thêm một trường static SEQUENCE_NAME, là một tham chiếu duy nhất đến chuỗi tự động tăng dần cho tập hợp người dùng.
Tôi cũng chú thích nó với @Transient để ngăn nó tồn tại cùng với các thuộc tính khác của model.
Tạo mới 1 record
Cho đến nay, tôi đã tạo ra các collection và model cần thiết. Bây giờ, tôi sẽ tạo một service sẽ tạo ra giá trị tự động tăng dần có thể được sử dụng làm id cho các thực thể của tôi.
KHOÁ HỌC LẬP TRÌNH DÀNH CHO NGƯỜI MỚI
Hãy tạo một SequenceGeneratorService có createSequence():
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;
}
Code language: JavaScript (javascript)
Bây giờ, chúng ta có thể sử dụng createSequence() trong khi tạo một bản ghi mới:
User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
user.setEmail("[email protected]");
userRepository.save(user);
Code language: JavaScript (javascript)
Để liệt kê tất cả người dùng, chúng tôi sẽ sử dụng UserRepository:
List<User> storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);
Code language: PHP (php)
Như hiện tại, chúng ta phải đặt trường id mỗi khi chúng ta tạo một phiên bản mới của model của mình. Chúng ta có thể phá vỡ quá trình này bằng cách tạo trình lắng nghe cho các sự kiện vòng đời Spring Data MongoDB.
Để làm điều đó, chúng tôi sẽ tạo một UserModelListener extends AbstractMongoEventListener<User> và sau đó chúng tôi sẽ ghi đè onBeforeConvert():
@Override
public void onBeforeConvert(BeforeConvertEvent<User> event) {
if (event.getSource().getId() < 1) {
event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
}
}
Code language: HTML, XML (xml)
Bây giờ, mỗi khi tôi lưu User mới, id sẽ được đặt tự động.
Kết luận
Chúng ta đã thấy cách tạo auto generate tăng dần cho trường id và mô phỏng hành vi tương tự như đã thấy trong cơ sở dữ liệu SQL.
Hibernate sử dụng một phương pháp tương tự để tạo các giá trị tự động tăng theo mặc định.
Leave a Reply