J'ai un problème dans mon projet avec une combinaison de Kotlin, SpringBoot 2.0 et MongoDB (avec Spring Data), avec @Transient
. Tout d'abord, voici comment j'ai déclaré mes classes de données
org.springframework.data.mapping.MappingException: No property child found on entity class com.example.sample.domain.Parent to bind constructor parameter to! at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:68) at org.springframework.data.mapping.model.SpELExpressionParameterValueProvider.getParameterValue(SpELExpressionParameterValueProvider.java:49) at org.springframework.data.convert.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.extractInvocationArguments(ClassGeneratingEntityInstantiator.java:250) at org.springframework.data.convert.ClassGeneratingEntityInstantiator$EntityInstantiatorAdapter.createInstance(ClassGeneratingEntityInstantiator.java:223) at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:84) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:272) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:245) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:194) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:190) at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:78) at org.springframework.data.mongodb.core.ReactiveMongoTemplate$ReadDocumentCallback.doWith(ReactiveMongoTemplate.java:2920) at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:100) at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:76) at com.mongodb.reactivestreams.client.internal.ObservableToPublisher$1.onNext(ObservableToPublisher.java:68) at com.mongodb.async.client.AbstractSubscription.onNext(AbstractSubscription.java:135) at com.mongodb.async.client.AbstractSubscription.processResultsQueue(AbstractSubscription.java:203) at com.mongodb.async.client.AbstractSubscription.tryProcessResultsQueue(AbstractSubscription.java:159) at com.mongodb.async.client.SingleResultCallbackSubscription$1.onResult(SingleResultCallbackSubscription.java:48) at com.mongodb.async.client.FindIterableImpl$1$1.onResult(FindIterableImpl.java:213) at com.mongodb.async.client.FindIterableImpl$1$1.onResult(FindIterableImpl.java:204) at com.mongodb.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:136) at com.mongodb.operation.AsyncQueryBatchCursor.next(AsyncQueryBatchCursor.java:100) at com.mongodb.async.client.FindIterableImpl$1.onResult(FindIterableImpl.java:204) at com.mongodb.async.client.FindIterableImpl$1.onResult(FindIterableImpl.java:198) at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) at com.mongodb.async.client.OperationExecutorImpl$1$1.onResult(OperationExecutorImpl.java:82) at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) at com.mongodb.operation.FindOperation$3.onResult(FindOperation.java:806) at com.mongodb.operation.OperationHelper$ReferenceCountedReleasingWrappedCallback.onResult(OperationHelper.java:364) at com.mongodb.operation.CommandOperationHelper$2.onResult(CommandOperationHelper.java:405) at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) at com.mongodb.internal.connection.DefaultServer$DefaultServerProtocolExecutor$2.onResult(DefaultServer.java:227) at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) at com.mongodb.internal.connection.CommandProtocolImpl$1.onResult(CommandProtocolImpl.java:85) at com.mongodb.internal.connection.DefaultConnectionPool$PooledConnection$1.onResult(DefaultConnectionPool.java:461) at com.mongodb.internal.connection.UsageTrackingInternalConnection$2.onResult(UsageTrackingInternalConnection.java:111) at com.mongodb.internal.async.ErrorHandlingResultCallback.onResult(ErrorHandlingResultCallback.java:49) at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:379) at com.mongodb.internal.connection.InternalStreamConnection$2$1.onResult(InternalStreamConnection.java:356) at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:651) at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback$MessageCallback.onResult(InternalStreamConnection.java:618) at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:494) at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:491) at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:236) at com.mongodb.internal.connection.InternalStreamConnection.readAsync(InternalStreamConnection.java:491) at com.mongodb.internal.connection.InternalStreamConnection.access$1000(InternalStreamConnection.java:74) at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:608) at com.mongodb.internal.connection.InternalStreamConnection$MessageHeaderCallback.onResult(InternalStreamConnection.java:593) at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:494) at com.mongodb.internal.connection.InternalStreamConnection$5.completed(InternalStreamConnection.java:491) at com.mongodb.connection.netty.NettyStream.readAsync(NettyStream.java:236) at com.mongodb.connection.netty.NettyStream.handleReadResponse(NettyStream.java:266) at com.mongodb.connection.netty.NettyStream.access$600(NettyStream.java:66) at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:325) at com.mongodb.connection.netty.NettyStream$InboundBufferHandler.channelRead0(NettyStream.java:322) at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:648) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:583) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:500) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:844)
Je comprends qu'il pourrait y avoir une meilleure façon de faire référence à Child
depuis le Parent , mais MongoDB est un existant.
Le problème ici est que je ne veux pas conserver la propriété child
dans Parent
, j'ai donc essayé d'annoter la propriété avec kotlin.jvm.Transient
, ou org.springframework.data.annotation.Transient
, ou les deux. Mais aucune combinaison ne semble résoudre mon problème. Le problème auquel je suis confronté est:
kotlin.jvm.Transient
, il est en cours de chargement, mais lorsque je le sauvegarde, il conservera la propriété child
avec lui li >
org.springframework.data.annotation.Transient
, il est impossible de lire avec la trace de pile: @Document data class Child(@Id val id: String?, val name: String) @Document data class Parent(@Id val id: String?, val child: Child? = null, val childId: String)
Toute aide est grandement appréciée
3 Réponses :
Puisque vous déclarez la propriété dans le constructeur, je pense que vous devez faire ce qui suit pour appliquer l'annotation au champ qui est implicitement créé, puisque Spring Data examinera les annotations du champ au lieu des annotations de la propriété du constructeur:
@get:Transient val child: Child? = null
Toujours le même. dans les 3 cas, l'erreur reste la même. :( @Document (collection = "parent") classe de données Parent (@Id val id: String? = null, @field: KotlinTransient @field: SpringTransient val child: Child? = null, val childId: String) < / code>
@JonathanHandoyo pourrait également essayer @get: Transient
au lieu de @field
toujours pas ... un autre modèle que j'ai trouvé fonctionné est de déclarer les membres "transitoires" comme var
s dans le corps de la classe de données
, mais ce n'est pas intuitif depuis La méthode .copy (...)
ne fonctionnera pas pour les membres déclarés dans le corps de la classe, et .equals (...)
ne les prendra pas en compte
Je viens de vérifier quel bytecode est généré avec quelques annotations différentes, et il me semble que @get: org.springframework.data.annotation.Transient val child
devrait fonctionner dans le constructeur. La méthode getter dans le bytecode a la même annotation qu'une méthode que je définis explicitement dans le corps de la classe avec l'annotation @Transient.
Ajoutez un nouveau constructeur kotlin et donnez-lui l'annotation @PersistenceConstructor
Je n'avais pas de problème parent-enfant, mais j'avais un transitoire et cela a résolu le problème pour moi.
Cela peut être très ennuyeux, mais c'est la manière très exacte dont les données Spring fonctionnent.
Les données Spring ont besoin d'un objet Child pour créer un objet Parent après avoir chargé les données Parent de Mongo, mais il n'y a pas de données Child dans Mongo , et l'exception est levée.
Donc, nous devrions d'abord créer un objet Parent sans objet Child, puis initialiser le champ enfant de l'objet Parent.
Je pense en utilisant @ org.springframework.data.annotation.Transient et @PersistenceConstructor en tant que code suivant est la meilleure façon de le faire.
@Document data class Child(@Id val id: String?, val name: String) @Document data class Parent(@Id val id: String?, @Transient val child: Child? = null, val childId: String) { @PersistenceConstructor constructor(id: String, childId: String): this(id = id, childId = childId, child = null) }