Mongodb Java: Perist POJO класс с универсальным полем - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть класс POJO, который выглядит следующим образом -

public class CacheEntity<V> {
  private String cacheId;
  private V value;

  public static final String ID_KEY = "cacheId";

  public CacheEntity() {
  }

  public CacheEntity(String cache_id, V value) {
    this.cacheId = cache_id;
    this.value = value;
  }

  public V getValue() {
    return value;
  }

  public void setValue(V value) {
    this.value = value;
  }

  public String getCacheId() {
    return cacheId;
  }

  public void setCacheId(String cacheId) {
    this.cacheId = cacheId;
  }
}

Я использую официальный драйвер mongodb-driver-sync версии 3.8.1

Как упомянуто в документации здесь , я использую CodecRegistry с автоматическим PojoCodecProvider. При попытке сохранить эту сущность я получаю следующую ошибку.

Exception in thread "main" org.bson.codecs.configuration.CodecConfigurationException: CacheEntity contains generic types that have not been specialised.
Top level classes with generic types are not supported by the PojoCodec.
    at org.bson.codecs.pojo.PojoCodecImpl.encode(PojoCodecImpl.java:93)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
    at com.mongodb.operation.BulkWriteBatch$WriteRequestEncoder.encode(BulkWriteBatch.java:398)
    at com.mongodb.operation.BulkWriteBatch$WriteRequestEncoder.encode(BulkWriteBatch.java:377)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
    at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
    at com.mongodb.internal.connection.BsonWriterHelper.writeDocument(BsonWriterHelper.java:75)
    at com.mongodb.internal.connection.BsonWriterHelper.writePayload(BsonWriterHelper.java:59)
    at com.mongodb.internal.connection.CommandMessage.encodeMessageBodyWithMetadata(CommandMessage.java:143)
    at com.mongodb.internal.connection.RequestMessage.encode(RequestMessage.java:138)
    at com.mongodb.internal.connection.CommandMessage.encode(CommandMessage.java:57)
    at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:244)
    at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:99)
    at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:444)
    at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:72)
    at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:200)
    at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:269)
    at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:131)
    at com.mongodb.operation.MixedBulkWriteOperation.executeCommand(MixedBulkWriteOperation.java:418)
    at com.mongodb.operation.MixedBulkWriteOperation.executeBulkWriteBatch(MixedBulkWriteOperation.java:256)
    at com.mongodb.operation.MixedBulkWriteOperation.access$700(MixedBulkWriteOperation.java:67)
    at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:200)
    at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:191)
    at com.mongodb.operation.OperationHelper.withReleasableConnection(OperationHelper.java:419)
    at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:191)
    at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:67)
    at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:193)
    at com.mongodb.client.internal.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:960)
    at com.mongodb.client.internal.MongoCollectionImpl.executeReplaceOne(MongoCollectionImpl.java:602)
    at com.mongodb.client.internal.MongoCollectionImpl.replaceOne(MongoCollectionImpl.java:578)
    at com.mongodb.client.internal.MongoCollectionImpl.replaceOne(MongoCollectionImpl.java:567)

Что я могу сделать, чтобы сделать эту работу? Спасибо.

1 Ответ

0 голосов
/ 05 июня 2019

Существуют следующие варианты, чтобы заставить его работать.

Подклассами

Если вы каждый раз создаете подкласс с конкретным универсальным типом, это работает:

public class MyClassCacheEntity extends CacheEntity<MyClass> {}

Используя BsonDocument + Джексон

Чтобы избежать создания подклассов, вы можете попытаться сохранить произвольные объекты как BsonDocument -s и сериализовать / десериализовать их, используя Джексона:

public class CacheEntity<V> {
  private String cacheId;
  private BsonDocument rawValue;

  // [...]

  // sets the value
  public void withValue(T o) {
    this.rawValue = BsonDocument.parse(new ObjectMapper().writeValueAsString(o))
  }

  // recovers the value
  public T value(Class<T> clazz) {
    return new ObjectMapper().readValue(this.rawValue.toJson(), clazz);
  }
}

Это работает до тех пор, пока вы не будете избегать соглашения о методах получения / установки для методов withValue() и value(), в противном случае Mongo начнет жаловаться на ту же проблему обобщений.

То же самое с чистым bson

Я думаю, вы также можете попробовать сделать то же самое, что и выше, используя org.bson.codecs.pojo.PojoCodec, который вы можете либо создать, либо извлечь из текущего реестра кодеков монго. Если вы знаете заранее и даете ему реальный класс, он не должен жаловаться на генерики.

...