Spring Boot Sping Boot 3.0.5 ReactiveMongoTemplate更新操作抛出DuplicateKeyException

bprjcwpo  于 2023-11-17  发布在  Spring
关注(0)|答案(1)|浏览(156)

我尝试将我的一些示例代码从Sping Boot 2.7更新到Sping Boot 3.0.5。

@Document(collection = "posts")
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Post implements Serializable {

    @Id
    private String id;

    @NotBlank
    private String title;

    @NotBlank
    private String content;

    @Builder.Default
    private Status status = DRAFT;

    @DocumentReference
    @Builder.Default
    List<Comment> comments = Collections.emptyList();

//    @Version
//    @Builder.Default
//    Long version = null;

    @CreatedDate
    private LocalDateTime createdDate;

    @CreatedBy
    private String createdBy;

    @LastModifiedDate
    private LocalDateTime lastModifiedDate;

    @LastModifiedBy
    private String lastModifiedBy;
}

字符串
我为它写了一个这样的测试。

@DataMongoTest
@Slf4j
@Testcontainers
public class PostRepositoryTest {

    @TestConfiguration
    @Import(MongoPostRepository.class)
    static class TestConfig {
    }

    @Container
    static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:4");

    @DynamicPropertySource
    static void registerMongoProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getReplicaSetUrl());
    }

    @Autowired
    PostRepository postRepository;

    @Autowired
    ReactiveMongoTemplate reactiveMongoTemplate;

    @SneakyThrows
    @BeforeEach
    public void setup() {
        var latch = new CountDownLatch(1);
        this.reactiveMongoTemplate.remove(Post.class).all()
            .doOnTerminate(latch::countDown)
            .subscribe(
                r -> log.debug("delete all posts: " + r),
                e -> log.debug("error: " + e), () -> log.debug("done")
            );
        latch.await(5000, TimeUnit.MILLISECONDS);
    }

    @Test
    public void testSavePost() {
        var content = "my test content";
        var title = "my test title";
        var saved = this.postRepository.create(title, content);

        StepVerifier.create(saved)
            .consumeNextWith(p -> {
                log.debug("consuming:: {}", p);
                assertThat(p.getTitle()).isEqualTo(title);
            })
            .expectComplete()
            .verify();

        var id = saved.block().getId();

        this.postRepository.addComment(id, "comment1")
            .then(this.postRepository.findById(id))
            .as(StepVerifier::create)
            .consumeNextWith(p -> {
                log.debug("after add comments: {}", p);
                assertThat(p.getComments()).isNotNull();
            })
            .expectComplete()
            .verify();
    }

}


addComment是一个使用ReactiveMongoTemplate的方法。

@Override
    public Mono<Boolean> addComment(String id, String content) {
        var comment = mongoTemplate.insert(Comment.builder().content(content).build());
        return comment.flatMap(c -> mongoTemplate.update(Post.class)
                .matching(where("id").is(id))
                .apply(new Update().push("comments").value(c))
                .first().hasElement()
        );
    }


但是mongoTemplate.update抛出了这样一个异常。

org.springframework.dao.DuplicateKeyException: Write operation error on server localhost:56524.
 Write error: WriteError{code=11000, message='E11000 duplicate key error collection: 
test.posts index: _id_ dup key: { _id: ObjectId('6428f50354bd273efaa52456') }', 
details={}}.


我必须制作Post文档来实现Persistable
我不知道为什么它在这里将现有实体确定为new

kqlmhetl

kqlmhetl1#

也许在你的例子中,这个类可以用@ ObjectiveAndHashCode注解?让Lombok生成equals(Object other)和hashCode()方法的实现。
@ browsAndHashCode(of = {“Your ID”,“Your fieldName1”,“Your fieldName2”}).
注意,如果你的类有一个超类,这是一个坏主意,因为超类也可能定义需要equals/hashCode代码的字段,但不会生成此代码。

相关问题