如何将 LinkingObject 用于 android

How to use LinkingObject for android

我想使用 Realm 建立类似 SQLite 的关系。

  1. 如果添加父项table时没有子项table,如何添加RealmList?
  2. 父table和子table之间是否存在实时link?
  3. 如何迁移RealmList,@LinkingObject

1.Parent Table

@RealmClass
open class ParentTable : RealmObject() {

    @PrimaryKey
    open var id : Long = 0

    open var parentname : String? = null

    var child : RealmList<ChildTable>? = null

}

2.Child Table

@RealmClass
open class ChildTable : RealmObject() {

    @PrimaryKey
    open var id : Long = 0

    open var parentId : Long? = 0    

    open var childName : String? = null

    @LinkingObjects("child")
    val parent : RealmResults<ParentTable>? = null

}

3.Application class

class HanmoApplication : MultiDexApplication() {

    override fun onCreate() {
        super.onCreate()

        initRealm()
    }

    private fun initRealm() {

        Realm.init(this)

        val config = RealmConfiguration.Builder()
                .name("hanmo.realm")
                .deleteRealmIfMigrationNeeded()
                .build()

        Realm.setDefaultConfiguration(config)
    }

    override fun onTerminate() {
        super.onTerminate()
        if (!Realm.getDefaultInstance().isClosed) {
            Realm.getDefaultInstance().close()
        }
    }
}

4.RealmHelper class

class RealmHelper {

var realm: Realm
    private set

init {
    realm = try {

        Realm.getDefaultInstance()

    } catch (e: Exception) {

        Log.d("Realm Exception", e.toString())

        val config = RealmConfiguration.Builder()
                .deleteRealmIfMigrationNeeded()
                .build()
        Realm.getInstance(config)
    }
}

fun selectTables() {
    val parent = queryAll(ParentTable::class.java)
    Log.d("parent", parent.toString())

    parent?.forEach {
        it.child?.forEach {
            Log.d("parent.child", it.toString())
        }
    }

    val child = queryAll(ChildTable::class.java)
    Log.d("child", child.toString())

    child?.forEach {
        Log.d("child.parent", it.parent?.toString())
    }
}

fun insertParent() {

    val parent = ParentTable()
    parent.id = 1
    parent.parentname = "First Parent"

    val childList = RealmList<ChildTable>()
    val child = queryAll(ChildTable::class.java)

    child?.forEach {
        val child = ChildTable()
        child.id = it.id
        child.childName = it.childName

        childList.add(child)
    }

    parent.child = childList

    addRealmListData(parent)
}


fun insertChild() {
    val maxId = realm.where(ChildTable::class.java).max("id")
    val nextId : Long =
            when(maxId) {
                null -> { 1 }
                else -> { maxId.toLong() + 1 }
            }

    val parentId = realm.where(ParentTable::class.java).findFirst()
    val child = ChildTable()
    child.id = nextId
    child.childName = "child num : $nextId"
    child.parentId = parentId?.id

    addData(child)
}

//Insert To Realm
fun <T : RealmObject> addData(data: T) {
    realm.executeTransaction {
        realm.copyToRealm(data)
    }
}

//Insert To Realm with RealmList
fun <T : RealmObject> addRealmListData(data: T) {
    realm.executeTransaction {
        realm.copyToRealmOrUpdate(data)
    }
}

fun <T : RealmObject> queryAll(clazz: Class<T>): RealmResults<T>? {
    return realm.where(clazz).findAll()
}

companion object {

    private var INSTANCE: RealmHelper? = RealmHelper()

    val instance: RealmHelper
        get() {
            if (INSTANCE == null) {
                INSTANCE = RealmHelper()
            }
            return INSTANCE as RealmHelper
        }
}

}

5.MainActivity class

class MainActivity : AppCompatActivity() {

lateinit var compositeDisposable: CompositeDisposable

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    compositeDisposable = CompositeDisposable()

    initParentTable()
    setButtonClick()
}

private fun initParentTable() {

    val parentTable = RealmHelper.instance.queryAll(ParentTable::class.java)

    if (parentTable?.isEmpty()!!){
        RealmHelper.instance.insertParent()
    }

}

private fun setButtonClick() {

    btn_addchild.clicks()
            .subscribe {
                RealmHelper.instance.insertChild()
            }.apply { compositeDisposable.add(this) }

    btn_parentquery.clicks()
            .subscribe {
                RealmHelper.instance.selectTables()
            }.apply { compositeDisposable.add(this) }

}

override fun onDestroy() {
    compositeDisposable.clear()
    super.onDestroy()
}

}

这是领域查询日志

fun selectTables() {
    val parent = queryAll(ParentTable::class.java)
    Log.d("parent", parent.toString())

    parent?.forEach {
        it.child?.forEach {
            Log.d("parent.child", it.toString())
        }
    }

    val child = queryAll(ChildTable::class.java)
    Log.d("child", child.toString())

    child?.forEach {
        Log.d("child.parent", it.parent?.toString())
    }
}

点击3次addChild按钮,查询,查看结果

03-26 12:22:17.534 29996-29996/com.hanmo.testforlinkingobject D/parent: [ParentTable = proxy[{id:1},{parentname:First Parent},{child:RealmList<ChildTable>[0]}]]
03-26 12:22:17.535 29996-29996/com.hanmo.testforlinkingobject D/child: [ChildTable = proxy[{id:1},{parentId:1},{childName:child num : 1}], ChildTable = proxy[{id:2},{parentId:1},{childName:child num : 2}], ChildTable = proxy[{id:3},{parentId:1},{childName:child num : 3}]]
03-26 12:22:17.536 29996-29996/com.hanmo.testforlinkingobject D/child.parent: []
03-26 12:22:17.536 29996-29996/com.hanmo.testforlinkingobject D/child.parent: []
03-26 12:22:17.537 29996-29996/com.hanmo.testforlinkingobject D/child.parent: []

=> 父 Table 和子 Table 未被 link 教育。

请问如何在没有Child时添加一个RealmList Table

If don't have a child table when add a parent table, how do add RealmList?

您需要 Child class 才能添加 RealmList<Child>

可以在事务中使用托管对象建立关系。

r.executeTransaction((realm) -> {
    ...
    Child child = realm.createObject(Child.class);
    Parent parent = realm.where(Parent.class)./*...*/.findFirst();
    parent.getChildren().add(child);
    ...
}

Is there a real-time link between the parent table and the child table?

How to migration RealmList, @LinkingObject

使用 realmObjectSchema.addRealmListField() method 添加 RealmList<T>

@LinkingObjects 是计算出来的,不是模式的一部分,因此不需要迁移。

Self-Answer

Parent Table

open class ParentTable : RealmObject() {

    @PrimaryKey
    open var id: Long = 0

    open var parentName : String? = null

    var child: RealmList<ChildTable>? = RealmList()
}

Child table

open class ChildTable : RealmObject() {

@PrimaryKey
open var id : Long = 0

open var childName : String? = null

open var parentName : String? = null

@LinkingObjects("child")
val parent: RealmResults<ParentTable>? = null

}

插入Parent数据

fun insertParent(parentName: String) {

    val maxId = realm.where(ParentTable::class.java).max("id")
    val nextId : Long =
            when(maxId) {
                null -> { 1 }
                else -> { maxId.toLong() + 1 }
            }

    val parent = ParentTable() // realm.createObject(Parent::class.java)
    parent.id = nextId
    parent.parentName = parentName

    addRealmListData(parent)

}

插入Child数据

fun insertChild(childName: String, parentName: String) {
    val maxId = realm.where(ChildTable::class.java).max("id")
    val nextId : Long =
            when(maxId) {
                null -> { 1 }
                else -> { maxId.toLong() + 1 }
            }

    val child = ChildTable() //realm.createObject(ChildTable::class.java)
    child.id = nextId
    child.childName = childName
    child.parentName = parentName

    var parent = realm.where(ParentTable::class.java).equalTo("parentName", parentName).findFirst()

    realm.executeTransaction {
        parent?.child?.add(child)
        realm.copyToRealmOrUpdate(child)
    }
}

addRealmListData()

//Insert To Realm with RealmList
fun <T : RealmObject> addRealmListData(data: T) {
    realm.executeTransaction {
        realm.copyToRealmOrUpdate(data)
    }
}
  • 问题解决

When I put the data of the child table, I put the data by specifying the parent table.

我的示例代码:enter link description here