为什么 MongoDB Morphia 无法在保存其他数据之前加载数据?

Why can't MongoDB Morphia load data before some other has been saved?

我正在尝试通过 Morphia (MongoDB) 映射对象。这工作正常,它们在数据库中是正确的,我可以从数据库中加载它们。但是,一旦我重新启动我的应用程序,我就会在尝试加载它们时遇到以下异常:

Exception in thread "pool-1-thread-1"
org.bson.codecs.configuration.CodecConfigurationException:
Failed to decode 'ClassB'. Decoding errored with:
A class could not be found for the discriminator: 'ClassA'.

跟踪堆栈:

Exception in thread "pool-1-thread-1" org.bson.codecs.configuration.CodecConfigurationException: Failed to decode 'ClassB'. Decoding errored with: A class could not be found for the discriminator: 'ClassA'.
at dev.morphia.mapping.codec.pojo.EntityDecoder.getCodecFromDocument(EntityDecoder.java:110)
at dev.morphia.mapping.codec.pojo.EntityDecoder.getCodecFromDocument(EntityDecoder.java:110)
at dev.morphia.mapping.codec.pojo.EntityDecoder.decode(EntityDecoder.java:46)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.decode(MorphiaCodec.java:66)
at dev.morphia.mapping.codec.CollectionCodec.decode(CollectionCodec.java:56)
at dev.morphia.mapping.codec.MorphiaCollectionCodec.decode(MorphiaCollectionCodec.java:22)
at dev.morphia.mapping.codec.MorphiaCollectionCodec.decode(MorphiaCollectionCodec.java:11)
at org.bson.codecs.DecoderContext.decodeWithChildContext(DecoderContext.java:96)
at dev.morphia.mapping.codec.pojo.EntityDecoder.decodeModel(EntityDecoder.java:66)
at dev.morphia.mapping.codec.pojo.EntityDecoder.decodeProperties(EntityDecoder.java:87)
at dev.morphia.mapping.codec.pojo.EntityDecoder.decode(EntityDecoder.java:43)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.decode(MorphiaCodec.java:66)
at dev.morphia.mapping.codec.pojo.EntityDecoder.decode(EntityDecoder.java:48)
at dev.morphia.mapping.codec.pojo.MorphiaCodec.decode(MorphiaCodec.java:66)
at com.mongodb.internal.operation.CommandResultArrayCodec.decode(CommandResultArrayCodec.java:52)
at com.mongodb.internal.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:60)
at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:87)
at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:42)
at org.bson.internal.LazyCodec.decode(LazyCodec.java:48)
at org.bson.codecs.BsonDocumentCodec.readValue(BsonDocumentCodec.java:104)
at com.mongodb.internal.operation.CommandResultDocumentCodec.readValue(CommandResultDocumentCodec.java:63)
at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:87)
at org.bson.codecs.BsonDocumentCodec.decode(BsonDocumentCodec.java:42)
at com.mongodb.internal.connection.ReplyMessage.<init>(ReplyMessage.java:51)
at com.mongodb.internal.connection.InternalStreamConnection.getCommandResult(InternalStreamConnection.java:476)
at com.mongodb.internal.connection.InternalStreamConnection.receiveCommandMessageResponse(InternalStreamConnection.java:366)
at com.mongodb.internal.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:279)
at com.mongodb.internal.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:100)
at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:490)
at com.mongodb.internal.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:71)
at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:253)
at com.mongodb.internal.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:202)
at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:118)
at com.mongodb.internal.connection.DefaultServerConnection.command(DefaultServerConnection.java:110)
at com.mongodb.internal.operation.CommandOperationHelper.executeCommand(CommandOperationHelper.java:345)
at com.mongodb.internal.operation.CommandOperationHelper.executeCommand(CommandOperationHelper.java:336)
at com.mongodb.internal.operation.CommandOperationHelper.executeCommandWithConnection(CommandOperationHelper.java:222)
at com.mongodb.internal.operation.FindOperation.call(FindOperation.java:658)
at com.mongodb.internal.operation.FindOperation.call(FindOperation.java:652)
at com.mongodb.internal.operation.OperationHelper.withReadConnectionSource(OperationHelper.java:583)
at com.mongodb.internal.operation.FindOperation.execute(FindOperation.java:652)
at com.mongodb.internal.operation.FindOperation.execute(FindOperation.java:80)
at com.mongodb.client.internal.MongoClientDelegate$DelegateOperationExecutor.execute(MongoClientDelegate.java:170)
at com.mongodb.client.internal.MongoIterableImpl.execute(MongoIterableImpl.java:135)
at com.mongodb.client.internal.MongoIterableImpl.iterator(MongoIterableImpl.java:92)
at dev.morphia.query.MorphiaQuery.prepareCursor(MorphiaQuery.java:320)
at dev.morphia.query.MorphiaQuery.iterator(MorphiaQuery.java:201)
at dev.morphia.query.MorphiaQuery.iterator(MorphiaQuery.java:196)
at dev.morphia.query.MorphiaQuery.iterator(MorphiaQuery.java:41)
at java.base/java.lang.Iterable.forEach(Iterable.java:74)
at mypacket.DatabaseManager.get(DatabaseManager.java:76)

加载数据时发生此异常。我发现它只有在我之前不将数据保存到数据库时才会发生。我可以将问题分解为以下代码:

要映射的类:

A类:

@NoArgsConstructor
@Entity
public class ClassA extends ClassB {

    public ClassA(String value) {
        super(value);
    }
}

B类:

@RequiredArgsConstructor
@NoArgsConstructor
@Entity
public class ClassB {
 
    @Id
    private int id = 0;
    @NonNull
    private String value;
}

容器类:

@Entity
public class ContainerClass {

    @Id @AutoID
    private int id;
    @Getter
    private List<ClassB> list = new ArrayList<>();
}

要执行的代码:

数据库连接:

datastore = Morphia.createDatastore(MongoClients.create(), "myproject");
Mapper mapper = datastore.getMapper();
mapper.mapPackage("mypacket");
datastore.ensureIndexes();

正在保存数据:

ContainerClass c = new ContainerClass();
c.getList().add(new ClassA("A class 1"));
c.getList().add(new ClassB("B class 1"));
datastore.save(c);

正在加载数据:

List<ContainerClass> list = get(ContainerClass.class);
System.out.println("found " + list.size() + " elements");

public static <T> List<T> get(Class<T> clazz) {
    List<T> list = new ArrayList<>();
    datastore.find(clazz).forEach(e -> list.add(e));
    return list;
}

调试步骤:

答: 当我在加载所有数据之前保存(只有一个对象)时。这很好用:found X elements

B: 当我在出现上述异常之前只尝试加载数据而不保存时。

数据库条目:

{
    "_id": 0,
    "_t": "ContainerClass",
    "list": [{
        "_id": 0,
        "_t": "ClassA",
        "value": "A class 1"
    }, {
        "_id": 0,
        "_t": "ClassB",
        "value": "B class 1"
    }]
}

一些附加数据:

环境:

评估问题原因:

这对我来说像是一个错误。受影响的 类 无法在启动期间正确 'loaded'。无论如何,一旦对象被映射,吗啡就可以暂时解决这个问题。

您应该始终将实体映射作为初始化的一部分。否则,Morphia 将不知道将该鉴别器映射到什么。