我正在尝试实现 Record 和 Tag 对象之间的多对多关系。每条记录可以有多个标签。
open class Record : RealmObject {
@PrimaryKey
var id: String = ""
var title: String = ""
var description: String = ""
var tags: RealmList<Tag> = realmListOf()
}
open class Tag : RealmObject {
@PrimaryKey
var id: String = ""
var name: String = ""
val record: RealmResults<Record> by backlinks(Record::tags)
}
在测试 Record 对象的保存时,我注意到以下问题。如果我们保存的记录带有标签表中不存在的标签,则会自动添加该标签。但是,如果我们尝试使用 Tags 表中已存在的标签保存记录,则会出现以下异常 - “尝试使用现有主键值“1”创建类型为“Tag”的对象”。
我编写了一个带有标签列表的 Record 对象,如下所示:
val record = Record().apply {
id = randomUUID()
title = "TestRecord"
description = "Desc"
tags = realmListOf(
Tag().apply {
id = "1"
name = "Tag1"
},
Tag().apply {
id = "2"
name = "Tag2"
}
)
}
realm.write {
copyToRealm(record)
}
请帮我找出我做错了什么?
我认为这里的问题是对 Realm 对象如何交互的理解;非托管与托管
让我用一些伪代码从高层次上解决这个问题
假设有 Record 和 Tag 对象,并且您的 Realm 数据库中尚不存在任何内容。记录有一个 RealmList of Tags
创建标签并将其添加到记录中。
var t0 = Tag(withPrimaryKey: 0)
var myRecord = Record()
myRecord.myTags.add(t0)
realm.add(myRecord)
这将会成功,并且标签和记录都将被添加到 Realm 中!但后来我们这样做了
let myRecord = read a record from Realm
var t0 = Tag(withPrimaryKey: 0)
myRecord.myTags.add(t0) //assume this is done within a write
上面会失败,因为主键为0的Tag已经存在,并且主键必须是唯一的
但是,假设 Realm 数据库只有一个条目,即主键为 0 的 Tag
let t0 = read Tag with primary key 0 from realm
let myRecord = Record()
myRecord.myTags.add(t0)
realm.add(myRecord) //assume this is done within a write
将会成功,并且主键为0的标签将不会被重复。由于它已经是一个托管对象(例如存储在领域中),因此它只是添加到 myRecord 中。
如果您知道特定对象的主键,您也可以Upsert它;该进程将创建该对象(如果该对象不存在),或者修改该对象(如果该对象存在)。