我怎么能避免DuplicateKeyException时更新MongoDB文档,当它不是从DB提取?



我有一个使用MongoDb的Spring Boot应用程序(2.5.3),我想在这个已经持续存在的MongoDb中更新一个文档。可以在我的REST控制器上更新这些文档,因此,应用程序创建用于更新文档的适当bean。这些对象/文档包含一个用@Id注释的复合ID,它们也有一个用@Version注释的版本属性。因此,它不是数据库生成的ID!

每当我执行<myRepository>.save(...)时,我得到一个DuplicateKeyException。

我怎么能这样成功呢?我宁愿不读操作。

BeanA -抽象基类:

@Data
@SuperBuilder
@NoArgsConstructor
@Validated
public abstract class BeanA {
@Version
private Long version;    // Needed to make @CreatedDate work during auditing.
@CreatedDate
private ZonedDateTime createdAt;
@LastModifiedDate
private ZonedDateTime modifiedAt;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String modifiedBy;
}

BeanB -具体类:

@Data
@Validated
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "BeanB")
public class BeanB extends BeanA {
@Id
private TheCompositeId compositeId;
}

CompundID类:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TheCompositeId {
@NotNull
@Size(min = 3, max = 3)
private String foo;
@NotNull
@Size(min = 2, max = 2)
private String bar;
@NotNull
@Size(min = 2, max = 2)
private String foobar;
}

所有"entity"类在应用存储库时,在映射到实体/文档类的应用程序中具有等效的dto。

测试类的测试摘录:

@Test
void shouldUpdate() throws Exception {
// given
var beanBApiModel = BeanBTestBuilder.aDefaultBeanBApiModel().build();
var json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(List.of(beanBApiModel));
// when & then
mvc.perform(post("/store").content(json).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(CompositeIdMapper.toCompositeId(beanBApiModel.getCompositeId()));
ResultActions res = mvc.perform(get("/find").content(json).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
var beanBDoc = objectMapper.readValue(res.andReturn().getResponse().getContentAsString(), BeanB.class);
beanBApiModel = BeanBMapper.toBeanBApiModel(beanBDoc);
beanBApiModel.setModifiedBy("xxx");

json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(List.of(beanBApiModel));
mvc.perform(put("/update").content(json).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
verify(beanBService).update(List.of(beanBApiModel));
}
测试类签名:
@SpringBootTest
@AutoConfigureMockMvc
class BeanBControllerIntegrationTest extends AbstractMongoDbIntegrationTest {
@Autowired
MockMvc mvc;
@SpyBean
BeanBService beanBService;
@Autowired
ObjectMapper objectMapper;
@Autowired
BeanBRepository beanBRepository;
...
}

BeanBService仅仅调用MongoRepository上的基本CRUD操作。

我必须:

  1. 从数据库中读取文档(如果文档在此期间被其他人修改)
  2. 设置版本属性

最新更新