Spring Data MongoDB @TypeAlias 升级后停止工作

SpringData MongoDB @TypeAlias ceased to work after upgrade

我正在尝试解决从 Spring Boot 2.3.1.RELEASE 升级到 Spring Boot 2.5.0 后的项目问题(不适用于 2.4.0+ ) @TypeAlias 似乎被忽略了。

我使用 Kotlin 和反应式方式来实现这一点。我将 @EntityScan@SpringBootApplication@EnableReactiveMongoRepositories[ 的 basePackages 设置为 com.example.ajax =27=].

这是我正在尝试实现的示例,它在 2.3.1 中运行(不介意结构):

sealed class ContactDBO

@TypeAlias("personalContact")
data class PersonalContactDBO(
    @Field("name") val name: String
) : ContactDBO()

@TypeAlias("organizationContact")
data class OrganizationContactDBO(
    @Field("identifier") val identifier: Long
) : ContactDBO()

@Document(collection = "contacts")
@TypeAlias("contacts")
data class ContactsDBO(

    @Id
    @Field("id")
    val managerId: UUID,

    @Field("managedContact")
    val contact: ContactDBO
)

并且当我使用 find 来自存储库(这是自定义的并且基于 reactiveMongoTemplate)时,此异常弹出窗口:

org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate com.example.ajax.ContactDBO using constructor fun <init>(): com.example.ajax.ContactDBO with arguments
        at org.springframework.data.mapping.model.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:79)
        Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Assembly trace from producer [reactor.core.publisher.MonoFlatMap] :
        reactor.core.publisher.Mono.flatMap(Mono.java:2859)
        org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$executeFindOneInternal(ReactiveMongoTemplate.java:2757)
Error has been observed at the following site(s):
        |_           Mono.flatMap ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$executeFindOneInternal(ReactiveMongoTemplate.java:2757)
        |_           Mono.flatMap ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.createMono(ReactiveMongoTemplate.java:649)
        |_        Mono.onErrorMap ⇢ at org.springframework.data.mongodb.core.ReactiveMongoTemplate.createMono(ReactiveMongoTemplate.java:650)
        |_     Mono.switchIfEmpty ⇢ at reactor.kotlin.core.publisher.MonoExtensionsKt.switchIfEmpty(MonoExtensions.kt:138)
...
Stack trace:
                at org.springframework.data.mapping.model.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:79)
                at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:89)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:369)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:342)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter$ConversionContext.convert(MappingMongoConverter.java:1916)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1641)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1690)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1653)
                at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:74)
                at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:53)
                at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.extractInvocationArguments(KotlinClassGeneratingEntityInstantiator.java:228)
                at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.createInstance(KotlinClassGeneratingEntityInstantiator.java:202)
                at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:89)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:369)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:342)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:278)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:274)
                at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:102)
                at org.springframework.data.mongodb.core.ReactiveMongoTemplate$ReadDocumentCallback.doWith(ReactiveMongoTemplate.java:3155)
                at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
                at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815)
                at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
                at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:160)
                at com.mongodb.reactivestreams.client.internal.BatchCursorPublisher.lambda$first[=13=](BatchCursorPublisher.java:106)
                at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:171)
                at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
                at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
                at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:160)
                at com.mongodb.reactivestreams.client.internal.MongoOperationPublisher.lambda$sinkToCallback(MongoOperationPublisher.java:550)
                at com.mongodb.internal.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:207)
                at com.mongodb.internal.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:146)
                at com.mongodb.reactivestreams.client.internal.BatchCursor.lambda$next[=13=](BatchCursor.java:35)
                at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
                at reactor.core.publisher.Mono.subscribe(Mono.java:4150)
                at reactor.core.publisher.Mono.subscribeWith(Mono.java:4265)
                at reactor.core.publisher.Mono.subscribe(Mono.java:3982)
                at com.mongodb.reactivestreams.client.internal.BatchCursorPublisher.lambda$first(BatchCursorPublisher.java:109)
                at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57)
                at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
                at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
                at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127)
                at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815)
                at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
                at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
                at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:160)
                at com.mongodb.reactivestreams.client.internal.MongoOperationPublisher.lambda$sinkToCallback(MongoOperationPublisher.java:550)
                at com.mongodb.reactivestreams.client.internal.OperationExecutorImpl.lambda$execute(OperationExecutorImpl.java:73)
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:48)
                at com.mongodb.internal.operation.FindOperation.onResult(FindOperation.java:755)
                at com.mongodb.internal.operation.OperationHelper$ReferenceCountedReleasingWrappedCallback.onResult(OperationHelper.java:532)
                at com.mongodb.internal.operation.CommandOperationHelper.onResult(CommandOperationHelper.java:483)
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:48)
                at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor.onResult(DefaultServer.java:286)
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:48)
                at com.mongodb.internal.connection.CommandProtocolImpl.onResult(CommandProtocolImpl.java:84)
                at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection.onResult(DefaultConnectionPool.java:530)
                at com.mongodb.internal.connection.UsageTrackingInternalConnection.onResult(UsageTrackingInternalConnection.java:142)
                at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:48)
                at com.mongodb.internal.connection.InternalStreamConnection.onResult(InternalStreamConnection.java:462)
                at com.mongodb.internal.connection.InternalStreamConnection.onResult(InternalStreamConnection.java:439)
                at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:744)
                at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:711)
                at com.mongodb.internal.connection.InternalStreamConnection.completed(InternalStreamConnection.java:581)
                at com.mongodb.internal.connection.InternalStreamConnection.completed(InternalStreamConnection.java:578)
                at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:322)
                at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:269)
                at com.mongodb.internal.connection.InternalStreamConnection.readAsync(InternalStreamConnection.java:578)
                at com.mongodb.internal.connection.InternalStreamConnection.access00(InternalStreamConnection.java:78)
                at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:701)
                at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:686)
                at com.mongodb.internal.connection.InternalStreamConnection.completed(InternalStreamConnection.java:581)
                at com.mongodb.internal.connection.InternalStreamConnection.completed(InternalStreamConnection.java:578)
                at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:322)
                at com.mongodb.connection.netty.NettyStream.handleReadResponse(NettyStream.java:350)
                at com.mongodb.connection.netty.NettyStream.access00(NettyStream.java:104)
                at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:409)
                at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:406)
                at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
                at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
                at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
                at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
                at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
                at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
                at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
                at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
                at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
                at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
                at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
                at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
                at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
                at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989)
                at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
                at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
                at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.ajax.ContactDBO]: Is it an abstract class?; nested exception is java.lang.InstantiationException
        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:216)
        at org.springframework.data.mapping.model.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:77)
        at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:89)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:369)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:342)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$ConversionContext.convert(MappingMongoConverter.java:1916)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$MongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1641)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1690)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter$AssociationAwareMongoDbPropertyValueProvider.getPropertyValue(MappingMongoConverter.java:1653)
        at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:74)
        at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:53)
        at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.extractInvocationArguments(KotlinClassGeneratingEntityInstantiator.java:228)
        at org.springframework.data.mapping.model.KotlinClassGeneratingEntityInstantiator$DefaultingKotlinClassInstantiatorAdapter.createInstance(KotlinClassGeneratingEntityInstantiator.java:202)
        at org.springframework.data.mapping.model.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:89)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:369)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:342)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:278)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:274)
        at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:102)
        at org.springframework.data.mongodb.core.ReactiveMongoTemplate$ReadDocumentCallback.doWith(ReactiveMongoTemplate.java:3155)
        at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:387)
        at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815)
        at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249)
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:387)
        at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:160)
        at com.mongodb.reactivestreams.client.internal.BatchCursorPublisher.lambda$first[=13=](BatchCursorPublisher.java:106)
        at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:171)
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:387)
        at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:387)
        at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:180)
        at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:387)

@Document 注释似乎修复了它。

@Document
@TypeAlias("personalContact")
data class PersonalContactDBO(
    @Field("name") val name: String
) : ContactDBO()

@Document
@TypeAlias("organizationContact")
data class OrganizationContactDBO(
    @Field("identifier") val identifier: Long
) : ContactDBO()