调用Spring Boot端点时如何在MongoDB中创建并更新对应数据记录
问题1:completedDate初始值处理
completedDate属于仅当业务完成后才会填充的字段,适合用Optional<Instant>类型定义,初始创建记录时传入Optional.empty()即可,获取到URL完成更新时再传入具体的时间值。
你现有的UserUrl类存在几个需要调整的点:
- 构造函数缺失
completeDate参数,导致类定义的字段无法正常赋值 withUrl方法错误重置了requestedDate,应该沿用创建时的原始请求时间version写死为0,不符合MongoDB乐观锁每次更新版本号自增的规则
修改后的UserUrl.java代码如下:
public class UserUrl{ public final MongoUserId mongoUserId; public final Optional<String> url; public final long version; public final Instant requestedDate; public final Optional<Instant> completeDate; public final State state; // 补全completeDate构造参数 public UserUrl(MongoUserId mongoUserId, Optional<String> url, long version, Instant requestedDate, Optional<Instant> completeDate, State state) { this.mongoUserId = mongoUserId; this.url = url; this.version = version; this.requestedDate = requestedDate; this.completeDate = completeDate; this.state = state; } public static UserUrl create(MongoUserId mongoUserId){ return new UserUrl( mongoUserId, Optional.empty(), 0, Instant.now(), // 初始创建时完成时间为空 Optional.empty(), State.REQUESTED ); } public UserUrl withUrl(String url){ return new UserUrl( this.mongoUserId, Optional.of(url), // 版本号自增适配乐观锁 this.version + 1, // 沿用原有请求时间不重置 this.requestedDate, // 填充完成时间 Optional.of(Instant.now()), State.COMPLETED ); } }
问题2:获取URL后更新原有记录的方案
Spring Data MongoDB的save方法是upsert逻辑,只要实体主键一致,第二次调用save就会覆盖原有记录。你需要在初始保存记录时持有返回的持久化实例,拿到URL后调用withUrl生成更新后的实体,再次保存即可。
你现有的Controller层需要调整的点:
- 方法声明返回值为
void和实际返回ResponseEntity的逻辑冲突,需要修正返回值类型 - 初始保存记录后没有持有实例,导致无法更新同一条记录
- 直接调用
getUrl.toString()未判空,会触发空指针异常
修改后的UserController.java代码如下:
@RequestMapping(value = "/trigger/url/{userId}", method = RequestMethod.GET) // 修正返回值类型 public ResponseEntity<String> getUrlForUser(@PathVariable("userId") String userId) { // 保存初始记录并持有持久化实例 UserUrl savedRequest = userUrlRepository.save(UserUrl.create(MongoUserId.of(userId))); URL getUrl = userDataService.getUrlUser(userId); // 提前判空避免空指针 if (getUrl != null) { String url = getUrl.toString(); // 生成更新后的实体并保存,覆盖原有记录 UserUrl completedRequest = savedRequest.withUrl(url); userUrlRepository.save(completedRequest); return new ResponseEntity<>(url, HttpStatus.OK); } else { // 业务失败时可根据需求补充更新记录状态为FAILED的逻辑 return new ResponseEntity<>(HttpStatus.NOT_FOUND); } }
补充说明
如果一个用户可能发起多笔请求,不要用MongoUserId作为唯一主键,需要给UserUrl类新增一个单独的@Id字段(比如String id)自动生成,避免同用户的多笔请求互相覆盖。
内容的提问来源于stack exchange,提问作者user9347049
相关产品推荐
相关产品推荐

