为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Micronaut 注册 MongoDB 编解码器

使用 Micronaut 注册 MongoDB 编解码器

BIG阳 2023-06-21 13:46:58
我正在使用 Micronaut 和 MongoDB 创建一个新的应用程序。关于我的一些数据库对象,我不得不陷入僵局。我有一个包含枚举字段的对象,我需要将其转换为可以保存的值(我打算将其作为字符串保存)。根据我的理解和收到的错误消息,我需要创建一个新的编解码器来处理这个问题(类似于 JPA 转换器)。虽然我找到了说明这一点的示例,但我对应该如何为 MongoClient 注册转换器感到有点困惑。我使用的是框架和相应 MongoClient 的最新 Micronaut 版本。以下是我得到的例外情况供参考:org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class fts.marketing.models.CampaignEmailStatus.    at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)    at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)    at com.mongodb.client.model.BuildersHelper.encodeValue(BuildersHelper.java:37)    at com.mongodb.client.model.Filters$SimpleEncodingFilter.toBsonDocument(Filters.java:1109)    at com.mongodb.client.model.Filters$AndFilter.toBsonDocument(Filters.java:946)    at com.mongodb.internal.operation.Operations.createFindOperation(Operations.java:142)    at com.mongodb.internal.operation.Operations.find(Operations.java:130)    at com.mongodb.internal.operation.AsyncOperations.find(AsyncOperations.java:85)    at com.mongodb.async.client.FindIterableImpl.createFindOperation(FindIterableImpl.java:229)    at com.mongodb.async.client.FindIterableImpl.asAsyncReadOperation(FindIterableImpl.java:225)    at com.mongodb.async.client.MongoIterableImpl.batchCursor(MongoIterableImpl.java:161)
查看完整描述

2 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

我认为用编解码器创建一个类并使其可注入应该足够了:


@Singleton

public class EnumCodec implements Codec<CampaignEmailStatus> {


  @Override

  public CampaignEmailStatus decode(BsonReader reader, DecoderContext decoderContext) {

    String enumString = reader.readString();

    return CampaignEmailStatus.valueOf(enumString);

  }


  @Override

  public void encode(BsonWriter writer, CampaignEmailStatus value, EncoderContext encoderContext) {

    String enumString = value.name();

    writer.writeString(enumString);

  }


  @Override

  public Class<CampaignEmailStatus> getEncoderClass() {

    return CampaignEmailStatus.class;

  }

}

编解码器的注入发生在这里

io.micronaut.configuration.mongo.reactive.DefaultReactiveMongoConfiguration#codecs

如果它不起作用,您应该能够从那里对其进行调试

PS:我没有测试上面的代码,但它应该给你一个想法


查看完整回答
反对 回复 2023-06-21
?
Cats萌萌

TA贡献1805条经验 获得超9个赞

MongoDB java 客户端在处理枚举方面不一致,并且仍未修复。

对于作为对象属性出现的枚举,有自动EnumPropertyCodecProvider编解码器实现并且开箱即用。但是,如果您将 enum 与com.mongodb.client.model.Filters它一起使用则不起作用,并且最终会出现问题的例外情况。

为 Micronaut 注册特定枚举编解码器的解决方案是有效的,但它需要为要处理的每个枚举定义一个编解码器 bean。这是适用于所有枚举的更通用的解决方案:

@Singleton

public class EnumCodecRegistry implements CodecRegistry {


    @SuppressWarnings("unchecked")

    @Override

    public <T> Codec<T> get(Class<T> clazz) {

        if (Enum.class.isAssignableFrom(clazz)) {

            return new EnumCodec(clazz);

        }

        return null;

    }


    @Override

    public <T> Codec<T> get(Class<T> clazz, CodecRegistry registry) {

        return get(clazz);

    }


    private static class EnumCodec<T extends Enum<T>> implements Codec<T> {

        private final Class<T> clazz;


        EnumCodec(final Class<T> clazz) {

            this.clazz = clazz;

        }


        @Override

        public void encode(final BsonWriter writer, final T value, final EncoderContext encoderContext) {

            writer.writeString(value.name());

        }


        @Override

        public Class<T> getEncoderClass() {

            return clazz;

        }


        @Override

        public T decode(final BsonReader reader, final DecoderContext decoderContext) {

            return Enum.valueOf(clazz, reader.readString());

        }

    }


}


查看完整回答
反对 回复 2023-06-21
  • 2 回答
  • 0 关注
  • 140 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信