1. 概述
在本教程中,我們將學習如何在 Spring Boot 中實現 MongoDB 的自動生成字段(順序字段)。
當我們使用 MongoDB 作為 Spring Boot 應用程序的數據庫時,由於 MongoDB 不支持使用 @GeneratedValue 註解,因此我們無法在模型中使用該註解。 換句話説,我們需要一種方法來模擬使用 JPA 和 SQL 數據庫時所獲得的相同效果。
解決此問題的通用解決方案非常簡單。 我們將創建一個集合(表)來存儲其他集合的生成序列。 在創建新記錄時,我們將使用它來檢索下一個值。
2. 依賴項
將以下 Spring Boot Starter 添加到我們的 <em pom.xml</em> 中:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</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
}讓我們創建一個名為 users 的集合,以及一個對應的模型對象,用於存儲使用我們系統的人員的詳細信息:
@Document(collection = "users")
public class User {
@Transient
public static final String SEQUENCE_NAME = "users_sequence";
@Id
private BigInteger id;
private String email;
//getters and setters omitted
}在上述創建的User模型中,我們添加了一個靜態字段SEQUENCE_NAME,它是對自動遞增序列的唯一引用,用於users集合。為了成功地生成ObjectId,您的類中Id屬性或字段的類型必須是String、ObjectId或BigInteger。
我們還使用@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<User>,然後我們將覆蓋 onBeforeConvert() 方法。
@Override
public void onBeforeConvert(BeforeConvertEvent<User> event) {
if (event.getSource().getId().intValue() < 1) {
event.getSource().setId(BigInteger.valueOf(
sequenceGenerator.generateSequence(User.SEQUENCE_NAME)));
}
}現在,每次保存一個新用户時,id會自動設置。
5. 結論
綜上所述,我們瞭解到如何生成用於 id 字段的序列化、自增值,並模擬了與 SQL 數據庫中相同的行為。
Hibernate 默認也使用類似的方法生成自增值。