gpt4 book ai didi

mongodb - 使用 Spring Data 将 Kotlin 内联类存储到 MongoDB

转载 作者:行者123 更新时间:2023-12-02 13:12:06 24 4
gpt4 key购买 nike

我正在尝试使用 Spring Data MongoDB (2.2.3-RELEASE) 将 Kotlin 的 (v1.3.61) 内联类存储到 MongoDB,但到目前为止没有运气。这是设置:

inline class UserId(@NotBlank val id: String) 


@Document(collection = "data")
class Data(
@Field("uid")
val userId: UserId
)

Spring 在创建它的 bean 时抛出以下异常:

Caused by: java.lang.ArrayIndexOutOfBoundsException: 1 at org.springframework.data.mapping.model.PreferredConstructorDiscoverer$Discoverers.buildPreferredConstructor(PreferredConstructorDiscoverer.java:221) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer$Discoverers.access$200(PreferredConstructorDiscoverer.java:89) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer$Discoverers$2.lambda$discover$0(PreferredConstructorDiscoverer.java:161) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_171] at java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958) ~[na:1.8.0_171] at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[na:1.8.0_171] at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498) ~[na:1.8.0_171] at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:1.8.0_171] at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_171] at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) ~[na:1.8.0_171] at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_171] at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464) ~[na:1.8.0_171] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer$Discoverers$2.discover(PreferredConstructorDiscoverer.java:164) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mapping.model.PreferredConstructorDiscoverer.discover(PreferredConstructorDiscoverer.java:77) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mapping.model.BasicPersistentEntity.(BasicPersistentEntity.java:105) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity.(BasicMongoPersistentEntity.java:74) ~[spring-data-mongodb-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mongodb.core.mapping.MongoMappingContext.createPersistentEntity(MongoMappingContext.java:91) ~[spring-data-mongodb-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mongodb.core.mapping.MongoMappingContext.createPersistentEntity(MongoMappingContext.java:39) ~[spring-data-mongodb-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:357) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mapping.context.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:323) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at java.lang.Iterable.forEach(Iterable.java:75) ~[na:1.8.0_171] at org.springframework.data.mapping.context.AbstractMappingContext.initialize(AbstractMappingContext.java:452) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.data.mapping.context.AbstractMappingContext.afterPropertiesSet(AbstractMappingContext.java:444) ~[spring-data-commons-2.2.3.RELEASE.jar:2.2.3.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE] ... 151 common frames omitted



堆栈跟踪非常模糊,但异常发生在 PreferredConstructorDiscovereruserId是构造函数的一部分,因此问题可能出在此处。

接下来是检查 Data 的字节码。类(class):
// ================net/test/Data.class
================= // class version 50.0 (50) // access flags 0x31
public final class net/test/Data {


@Lorg/springframework/data/mongodb/core/mapping/Document;(collection="data")

// access flags 0x12 private final Ljava/lang/String; userId @Lorg/springframework/data/mongodb/core/mapping/Field;(value="uid") @Lorg/jetbrains/annotations/NotNull;() // invisible

// access flags 0x11 public final getUserId()Ljava/lang/String; @Lorg/jetbrains/annotations/NotNull;() // invisible L0
LINENUMBER 10 L0
ALOAD 0
GETFIELD net/test/Data.userId : Ljava/lang/String;
ARETURN L1
LOCALVARIABLE this Lnet/test/Data; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1

// access flags 0x2 private <init>(Ljava/lang/String;)V L0
LINENUMBER 7 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
ALOAD 0
ALOAD 1
PUTFIELD net/test/Data.userId : Ljava/lang/String;
RETURN L1
LOCALVARIABLE this Lnet/test/Data; L0 L1 0
LOCALVARIABLE userId Ljava/lang/String; L0 L1 1
MAXSTACK = 2
MAXLOCALS = 2

// access flags 0x1001 public synthetic <init>(Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
// annotable parameter count: 2 (visible)
// annotable parameter count: 2 (invisible) L0
LINENUMBER 7 L0
ALOAD 0
ALOAD 1
INVOKESPECIAL net/test/Data.<init> (Ljava/lang/String;)V
RETURN L1
LOCALVARIABLE this Lnet/test/Data; L0 L1 0
LOCALVARIABLE userId Ljava/lang/String; L0 L1 1
LOCALVARIABLE $constructor_marker Lkotlin/jvm/internal/DefaultConstructorMarker; L0 L1 2
MAXSTACK = 2
MAXLOCALS = 3

@Lkotlin/Metadata;(mv={1, 1, 16}, bv={1, 0, 3}, k=1, d1={"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\u0008\u0005\u0008\u0007\u0018\u00002\u00020\u0001B\u0010\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u00f8\u0001\u0000\u00a2\u0006\u0002\u0010\u0004R\u001b\u0010\u0002\u001a\u00020\u00038\u0006X\u0087\u0004\u00f8\u0001\u0000\u00a2\u0006\n\n\u0002\u0010\u0007\u001a\u0004\u0008\u0005\u0010\u0006\u0082\u0002\u0004\n\u0002\u0008\u0019\u00a8\u0006\u0008"}, d2={"Lnet/test/Data;", "", "userId", "Lnet/test/UserId;", "(Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V", "getUserId", "()Ljava/lang/String;", "Ljava/lang/String;", "core"}) // compiled from: Data.kt }


// ================META-INF/core.kotlin_module =================

这是 PreferredConstructorDiscoverer 的相关行 221来自 Spring 源代码:
String name = parameterNames == null ? null : parameterNames[i];

我是一个完全不懂字节码的菜鸟,但其中一个可能会立即看到问题。

我尝试过的其他方法是实现两个 org.springframework.core.convert.converter.Converter<UserId,String> 类型的自定义转换器反之亦然。但是,bean 实例化发生在任何转换发生之前,因此这似乎无关紧要。

我知道内联类在 Kotlin 1.3 中仍处于试验阶段,但实际问题可能出在其他地方。有人有想法吗?

顺便说一句,从 UserId 更改类型时至 String一切正常。

最佳答案

我正在为此使用一种解决方法,方法是引入一个私有(private)字段。

inline class UserId(@NotBlank val id: String = UUID.randomUUID().toString())

@Document(collection = "data")
data class Data(
@Transient val userId: UserId = UserId()
) {
@Id private val idData = userId.id
}

但是使用这种方法,您应该从扩展 CRUD-Interfaces 切换到自己实现基本操作(否则 ID 类没有意义):

// introduce some extension functions for easier use with mongo-template
suspend inline fun <T> ReactiveMongoTemplate.saveAndAwait(entity: T) : T =
save(entity).awaitSingle()
suspend inline fun <reified T> ReactiveMongoTemplate.findById(id: Any) : T =
findById(id, T::class.java).awaitSingle()

@ExperimentalCoroutinesApi
@Repository
internal class DataRepository(
private val template: ReactiveMongoTemplate
) {
suspend fun save(order: Order) : Order = template.saveAndAwait(order)
suspend fun findById(orderId: OrderId): Order = template.findById(orderId.id)
}

如果它值得开销?
临:
  • 键入的 ID
  • 在 Mongo 中,id 列仍然是一个原始的

  • 缺点:
  • 存储库变得更加复杂

  • 如果 DATACMNS-1517将来某个时候会修复,适应应该相对容易(大部分存储库的实现被删除,有利于扩展接口(interface))。

    关于mongodb - 使用 Spring Data 将 Kotlin 内联类存储到 MongoDB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59848266/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com