You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:06:07