当前位置: 首页 > 知识库问答 >
问题:

使用Spring数据将Kotlin内联类存储到MongoDB

阳福
2023-03-14

我试图使用Spring Data MongoDB(2.2.3-发行版)将Kotlin的(v1.3.61)内联类存储到MongoDB中,但到目前为止还没有成功。这是设置:

inline class UserId(@NotBlank val id: String) 

而且

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

stacktrace相当模糊,但异常发生在PreferredConstructorDiscoverer中,并且userid是构造函数的一部分,因此问题可能就在那里。

接下来是检查data类的字节代码:

// ================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 =================            

这是来自Spring源代码的PreferredConstructorDiscoverer的相关行221:

String name = parameterNames == null ? null : parameterNames[i];

我完全不懂字节码,但其中一个可能会马上看到问题。

我还尝试过实现两个类型为org.springframework.core.convert.converter.converter 的自定义转换器,反之亦然。但是,bean实例化发生在任何转换发生之前,因此这似乎是不相关的。

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

顺便说一下,当将类型从userid更改为string时,一切正常。

共有1个答案

秦博延
2023-03-14

我使用了一种变通方法,通过引入一个私有字段。

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-class就没有意义了):

kotlin prettyprint-override">// 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)
}

如果它值得开销?赞成:

    null
    null

如果DATACMNS-1517在将来的某个时候被修复,那么适应应该是相对容易的(大多数情况下存储库的实现被移除,而被扩展接口所支持)。

 类似资料:
  • 我是Hadoop的新手,需要将Hadoop数据存储到MongoDB中。在这里,我使用Pig将Hadoop中的数据存储到MongoDB中。 在给定命令的帮助下,我在Pig Grunt shell中下载并注册了以下驱动程序, 在此之后,我使用以下命令成功地从MongoDB获取了数据。 然后,我尝试使用以下命令将数据从pig bag插入MongoDB,并获得成功。 然后我尝试使用下面的命令Mongo更新

  • 对于spring boot、spring jpa、spring amqp,我有以下场景: 我的应用程序负责将数据复制到不同的数据库,但使用相同的实体,我必须存储/更新数据的数据库将在运行时根据即将到来的rabbit amqp数据决定。 我知道,使用spring jpa,我们可以拥有多个数据源,而使用@EnableJpaRepositories,我们可以通过如下方式指定基本包来选择repositor

  • 我在使用Spring批处理作业读取大型CSV文件(几百万条记录)并将其中的记录保存到数据库时遇到了问题。该作业使用< code>FlatFileItemReader来读取CSV,并使用< code>JpaItemWriter将读取和处理的记录写入数据库。问题是< code>JpaItemWriter在将另一个项目块刷新到数据库后没有清除持久性上下文,作业以< code>OutOfMemoryErr

  • 问题内容: 我想使用新CKEditor 4(http://docs.ckeditor.com/#!/guide/dev_inline- section-2 )的“内联编辑” ,但是找不到如何使用PHP保存数据的任何示例/ MySQL。你能帮助我吗? 问题答案: 您需要一些AJAX魔术。通过页面内的JavaScript,您可以编辑HTML。然后,将其发送到服务器,PHP脚本将其获取并可以将其传递到M

  • 正如标题所说,当我将spring数据rest存储库添加到现有的spring数据rest webmvc项目中时,我开始在项目运行中出错。 我试图使用@ConvertBy(MyConverter.class)在实体中遵循此链接进行嵌入ID转换。然而,仅仅添加jar就会导致以下错误和大量o. s. c. i. s. PathMatchingResourcePatterResolver日志。

  • 问题内容: 有人可以告诉我,在以下情况下如何进行? 接收文件(MS文件,ODS,PDF) 通过Apache Tika提取公元核心元数据+通过jackrabbit-content-extractors提取内容 使用Jackrabbit将文档(内容)及其元数据存储到存储库中 ? 检索文档+元数据 我对第3点和第4点感兴趣… 详细信息:该应用程序正在以交互方式处理文档(一些分析-语言检测,单词计数等。+