为什么 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"
}]
}
一些附加数据:
环境:
- mongodb-驱动程序同步 (4.2.3)
- 吗啡核心 (2.1.5)
- slf4j-简单 (1.8.0-beta2)
- 龙目岛 (1.18.20)
评估问题原因:
这对我来说像是一个错误。受影响的 类 无法在启动期间正确 'loaded'。无论如何,一旦对象被映射,吗啡就可以暂时解决这个问题。
您应该始终将实体映射作为初始化的一部分。否则,Morphia 将不知道将该鉴别器映射到什么。
我正在尝试通过 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"
}]
}
一些附加数据:
环境:
- mongodb-驱动程序同步 (4.2.3)
- 吗啡核心 (2.1.5)
- slf4j-简单 (1.8.0-beta2)
- 龙目岛 (1.18.20)
评估问题原因:
这对我来说像是一个错误。受影响的 类 无法在启动期间正确 'loaded'。无论如何,一旦对象被映射,吗啡就可以暂时解决这个问题。
您应该始终将实体映射作为初始化的一部分。否则,Morphia 将不知道将该鉴别器映射到什么。