Spring Boot中MongoDB Long类型自增ID生成失败问题
解决Spring Data MongoDB中Long类型自增ID的问题
问题描述
在创建名为Pallet的MongoDB集合时,想要让Long类型的idPallet字段实现自增,但新增数据时总是抛出异常:
"message": "Cannot autogenerate id of type java.lang.Long for entity of type com.example.ShippingTest.collections.Pallet"
试过移除@SequenceGenerator注解,问题依然存在;添加@Entity注解后又出现新错误:'Basic' attribute type should not be a container,还要求再添加一个ID。
问题原因
Spring Data MongoDB不支持JPA的@GeneratedValue、@SequenceGenerator这类注解——这些是专为关系型数据库设计的。MongoDB默认用ObjectId作为主键,要实现Long类型的自增ID,得手动处理序列生成逻辑。
解决方案步骤
1. 初始化序列集合
先在MongoDB里创建一个专门存序列的集合(比如叫sequence),用来记录每个业务集合的当前自增值。可以手动插入初始数据:
{ "_id": "pallet_seq", "seq": 0 }
2. 实现自增ID生成器
创建一个监听类,在Pallet数据插入前自动生成自增ID:
import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; import org.springframework.data.mongodb.core.FindAndModifyOptions; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Component; @Component public class PalletIdGenerator extends AbstractMongoEventListener<Pallet> { private final MongoTemplate mongoTemplate; public PalletIdGenerator(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } @Override public void onBeforeConvert(BeforeConvertEvent<Pallet> event) { Pallet pallet = event.getSource(); // 只有当idPallet为空时才生成自增ID if (pallet.getIdPallet() == null) { pallet.setIdPallet(getNextSequence("pallet_seq")); } } // 获取下一个序列值 private Long getNextSequence(String seqName) { Query query = new Query(Criteria.where("_id").is(seqName)); Update update = new Update().inc("seq", 1); // 不存在则插入,返回更新后的文档 FindAndModifyOptions options = new FindAndModifyOptions().returnNew(true).upsert(true); Sequence sequence = mongoTemplate.findAndModify(query, update, options, Sequence.class); return sequence.getSeq(); } }
同时创建对应序列集合的实体类:
import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; @Data @Document(collection = "sequence") public class Sequence { @Id private String id; private Long seq; }
3. 修改Pallet实体类
删掉所有JPA相关注解,只保留Spring Data MongoDB的注解:
package com.example.ShippingTest.collections; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import java.util.List; @Data @NoArgsConstructor @AllArgsConstructor @Document(collection = "Pallet") // 指定MongoDB对应的集合名 public class Pallet { @Id private Long idPallet; private int maxPallet; private String typePallet; private String shipAddress; private String shipLocation; private String shipCountry; private String destination; private List<PS> PackingSlip; }
4. 测试功能
现在调用POST接口/pallets新增Pallet数据,idPallet会自动从1开始递增,之前的异常也不会再出现了。
内容的提问来源于stack exchange,提问作者hazem_bensaid
相关产品推荐
相关产品推荐

