CustomConverter 未应用于 ReactiveMongoTemplate

问题描述 投票:0回答:1

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 spring-boot spring-data-mongodb spring-data-mongodb-reactive
1个回答
0
投票

要执行更新插入,您没有以正确的方式使用 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。

© www.soinside.com 2019 - 2024. All rights reserved.