MongoDb Java-更深的多态树
MongoDb Java- deeper polymorph tree
对于要存储在 MongoDb 中的对象,我有以下多态结构:
InventoryItem (abstract)
/ \
Tracked Item AmountItem (Abstract)
/ \
SimpleAmountItem ListAmountItem
有:(完整代码here (Github))
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "storedType"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = SimpleAmountItem.class, name = "AMOUNT_SIMPLE"),
@JsonSubTypes.Type(value = ListAmountItem.class, name = "AMOUNT_LIST"),
@JsonSubTypes.Type(value = TrackedItem.class, name = "TRACKED")
})
@BsonDiscriminator
public abstract class InventoryItem<T> extends ImagedMainObject {
@NonNull
@NotNull
private Map<@NonNull ObjectId, @NonNull T> storageMap = new LinkedHashMap<>();
private final StoredType storedType;
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class TrackedItem extends InventoryItem<Map<@NotBlank String, @NotNull TrackedStored>> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@ValidHeldStoredUnits
public abstract class AmountItem<T> extends InventoryItem<T> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class SimpleAmountItem extends AmountItem<AmountStored> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class ListAmountItem extends AmountItem<List<@NotNull AmountStored>> {
//...
}
如图所示,TrackedItem
可以由 Mongo 适当地处理、存储/检索等。但是,ListAmountItem
和 SimpleAmountItem
都不能,具有以下内容错误:
Encoding a ListAmountItem: 'ListAmountItem()' failed with the following exception:
Failed to encode 'ListAmountItem'. Encoding 'storageMap' errored with: Can't find a codec for class java.lang.Object.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:105)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:359)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:218)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:519)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess[=14=](SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.run(VertxRequestHandler.java:91)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder.runWith(VertxCoreRecorder.java:543)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.bson.codecs.configuration.CodecConfigurationException: An exception occurred when encoding using the AutomaticPojoCodec.
Encoding a ListAmountItem: 'ListAmountItem()' failed with the following exception:
Failed to encode 'ListAmountItem'. Encoding 'storageMap' errored with: Can't find a codec for class java.lang.Object.
看来 Mongo 可以调和超类的 direct/first 个后代,但如果继承树比这更深,则不会。这是设计的问题、错误还是我可以调整以解决的问题?
在我看来,Mongo 在尝试将 Simple/ListAmountItem
调和为普通的 AmountItem
时卡住了,这对于它失败的原因是有道理的,但不是很清楚如何修复它。 @BsonDiscriminator
似乎相当简单,尤其是。与杰克逊相比。
我会注意到我正在 Quarkus 中实现它 2.7.5.Final
。
看起来可能支持指定已知类型,但我没有看到类似的 java 注释:https://mongodb.github.io/mongo-csharp-driver/2.6/reference/bson/mapping/polymorphism/
看来我发现了一个错误:https://jira.mongodb.org/projects/JAVA/issues/JAVA-4578
理想情况下,问题会在工单完成后得到解决。
现在,我只是展平了我的对象树,复制了一些代码,我知道我可以在将来移动到更合适的状态
对于要存储在 MongoDb 中的对象,我有以下多态结构:
InventoryItem (abstract)
/ \
Tracked Item AmountItem (Abstract)
/ \
SimpleAmountItem ListAmountItem
有:(完整代码here (Github))
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "storedType"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = SimpleAmountItem.class, name = "AMOUNT_SIMPLE"),
@JsonSubTypes.Type(value = ListAmountItem.class, name = "AMOUNT_LIST"),
@JsonSubTypes.Type(value = TrackedItem.class, name = "TRACKED")
})
@BsonDiscriminator
public abstract class InventoryItem<T> extends ImagedMainObject {
@NonNull
@NotNull
private Map<@NonNull ObjectId, @NonNull T> storageMap = new LinkedHashMap<>();
private final StoredType storedType;
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class TrackedItem extends InventoryItem<Map<@NotBlank String, @NotNull TrackedStored>> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@ValidHeldStoredUnits
public abstract class AmountItem<T> extends InventoryItem<T> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class SimpleAmountItem extends AmountItem<AmountStored> {
//...
}
@EqualsAndHashCode(callSuper = true)
@Data
public class ListAmountItem extends AmountItem<List<@NotNull AmountStored>> {
//...
}
如图所示,TrackedItem
可以由 Mongo 适当地处理、存储/检索等。但是,ListAmountItem
和 SimpleAmountItem
都不能,具有以下内容错误:
Encoding a ListAmountItem: 'ListAmountItem()' failed with the following exception:
Failed to encode 'ListAmountItem'. Encoding 'storageMap' errored with: Can't find a codec for class java.lang.Object.
A custom Codec or PojoCodec may need to be explicitly configured and registered to handle this type.
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:105)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:359)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:218)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:519)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess[=14=](SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.run(VertxRequestHandler.java:91)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder.runWith(VertxCoreRecorder.java:543)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: org.bson.codecs.configuration.CodecConfigurationException: An exception occurred when encoding using the AutomaticPojoCodec.
Encoding a ListAmountItem: 'ListAmountItem()' failed with the following exception:
Failed to encode 'ListAmountItem'. Encoding 'storageMap' errored with: Can't find a codec for class java.lang.Object.
看来 Mongo 可以调和超类的 direct/first 个后代,但如果继承树比这更深,则不会。这是设计的问题、错误还是我可以调整以解决的问题?
在我看来,Mongo 在尝试将 Simple/ListAmountItem
调和为普通的 AmountItem
时卡住了,这对于它失败的原因是有道理的,但不是很清楚如何修复它。 @BsonDiscriminator
似乎相当简单,尤其是。与杰克逊相比。
我会注意到我正在 Quarkus 中实现它 2.7.5.Final
。
看起来可能支持指定已知类型,但我没有看到类似的 java 注释:https://mongodb.github.io/mongo-csharp-driver/2.6/reference/bson/mapping/polymorphism/
看来我发现了一个错误:https://jira.mongodb.org/projects/JAVA/issues/JAVA-4578
理想情况下,问题会在工单完成后得到解决。
现在,我只是展平了我的对象树,复制了一些代码,我知道我可以在将来移动到更合适的状态