Mongodb java: Perist POJO class with generic field

杀马特。学长 韩版系。学妹 提交于 2019-12-24 03:37:46

问题


I have a POJO class which looks like this-

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;
  }
}

I am using official driver mongodb-driver-sync version 3.8.1

As mentioned in the documentation here, I am using CodecRegistry with automatic PojoCodecProvider. I am getting the following error when I try to persist this entity.

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)

What can I do to make this work? Thank You.


回答1:


There are following options to make it working.

By subclassing

If you subclass with concrete generic type each time, it works:

public class MyClassCacheEntity extends CacheEntity<MyClass> {}

By using BsonDocument + Jackson

To avoid subclassing you can try store arbitrary objects as BsonDocument-s and serialize/deserialize them using Jackson:

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);
  }
}

This works until you avoid getters/setters convention for withValue() and value() methods, otherwise Mongo starts to complain about the same generics issue.

Same with pure bson

I think, you can also try to do it the same as above using org.bson.codecs.pojo.PojoCodec which you can either create or extract from the current mongo codecs registry. If you know in advance and give it the real class, it shouldn't complain about generics.



来源:https://stackoverflow.com/questions/52197137/mongodb-java-perist-pojo-class-with-generic-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!