Spring 社区您好,
我有一个带有 Mongo DB 的 Spring Boot 3 应用程序。我使用 Spring data mongo 反应式与数据库进行通信,除了这个问题之外,它的效果很好。
我有一个属性,我想用另一个类封装,但我需要相同的数据库结构以实现兼容性。
@Data
@Builder
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class TestType {
String value;
}
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Document(collection = "entity")
@AllArgsConstructor
@NoArgsConstructor
@FieldNameConstants
public class Entity {
public static final String COLLECTION_NAME = "entity";
@Id
UUID id;
@Builder.Default
@Field(name = Fields.data)
List<SomeOtherData> data = new ArrayList<>();
@Builder.Default
TestType testType = new TestType("payload");
}
如果不使用转换器编写,此代码将生成以下文档:
{
"id": someID,
"data": {},
"testType":{"value":"payload"}
}
但我需要它看起来像这样:
{
"id": someID,
"data": {},
"testType":"payload"
}
所以我添加了两个 CustomConverters 并添加了一个 bean 来提供 mongoCustomConversions:
@WritingConverter
public class TestTypeStringConverter implements Converter<TestType, String> {
@Override
public String convert(TestType source) {
return source.getValue();
}
}
@ReadingConverter
public class StringTestTypeConverter implements Converter<String, TestType> {
@Override
public TestType convert(@NonNull String source) {
return new TestType(source);
}
}
@Bean
public MongoCustomConversions mongoCustomConversions() {
return new MongoCustomConversions(List.of(
new TestTypeStringConverter(),
new StringTestTypeConverter()
));
}
我使用 mongoTemplate 将更改写入数据库:
private UpdateOneModel<Document> createUpdate(Entity newEntity) {
var query = new Query().addCriteria(new Criteria(UNDERSCORE_ID).is(newEntity.getId()));
var updateVehicle = new Update();
var options = new UpdateOptions();
options.upsert(true);
updateVehicle.set(Entity.Fields.data, newEntity.getData());
updateVehicle.set(Entity.Fields.testType, newEntity.getTestType());
return new UpdateOneModel<>(query.getQueryObject(), updateVehicle.getUpdateObject(), options);
}
private Mono<BulkWriteResult> execute(String collectionName, UpdateOneModel<Document> updateModelList) {
return reactiveMongoTemplate.getCollection(collectionName)
.flatMap(c -> Mono.from(c.bulkWrite(List.of(updateModelList))));
}
但我的对象仍然被编写为没有转换器。
调试确认 mongoTemplate 包含我的转换器的实例。两者都分别列在转换器以及写入和读取对中。 我尝试更改数据类型,但这也没有改变任何内容。 那时我已经没有想法了。
我做错了什么?
感谢您的支持。
要执行更新插入,您没有以正确的方式使用 Spring。相反,您从 com.mongodb 包中调用
bulkWrite
方法。您正确定义的转换器是 SpringData Mongo 中存在的 Spring 概念。
我使用了相同的reactiveMongoTemplate,但使用了 SpringData Mongo 中的 upsert 方法,并且它按预期工作。
我在这里做了一个示例提交:https://github.com/sbernardo/spring-issues-examples/tree/main/sof-questions-77612149
无论如何,您仍然可以使用当前的方法进行批量操作(您可以在我的存储库中找到此代码):
var entity = new Entity(UUID.fromString("7f6a35fb-a449-4e31-b9c1-7592cc969d83"), new TestType("HelloValue"));
Update update = new Update();
update.set(Entity.Fields.testType, entity.getTestType());
update.set("field2", "otherFieldValue");
return reactiveMongoTemplate
.bulkOps(BulkOperations.BulkMode.UNORDERED, Entity.class)
.upsert(Query.query(new Criteria(UNDERSCORE_ID).is(entity.getId())), update)
.execute()
.block()
.toString();
我正在使用 spring-boot 3.2.0 和 java 21。