1

I would like to make a relationship like SQLite using Realm.

  1. If don't have a child table when add a parent table, how do add RealmList?
  2. Is there a real-time link between the parent table and the child table?
  3. How to migration 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()
}

}

this is realm query log

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())
    }
}

Click on addChild button three times, query, and see results

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: []

=> Parent Table and Child Table are not linked.

please How to add a RealmList when there is no Child Table

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
hanmolee
  • 253
  • 3
  • 9
  • `If don't have a child table when add a parent table, how do add RealmList?` what does that mean? You want to create links to an object type that doesn't exist? – EpicPandaForce Mar 26 '18 at 09:49
  • okay, i can't answer until you answer my question :p – EpicPandaForce Mar 26 '18 at 09:57
  • i think he want don't put dummy data to child table. – 최봉재 Mar 26 '18 at 10:08
  • @EpicPandaForce put the data in the child table, but I could not see it in the parent table, obviously the two seem to be connected. The child table is not created until the parent table is created. what should I do? – hanmolee Mar 26 '18 at 10:16

2 Answers2

0

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

You need to have the Child class to add a RealmList<Child>.

Relationships can be built using managed objects, in a transaction.

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?

yes

How to migration RealmList, @LinkingObject

Add RealmList<T> using realmObjectSchema.addRealmListField() method.

@LinkingObjects are computed and not part of the schema, so no migration needed for that.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • Thank you for the answer. Yes. I saw your official document and implemented it the same way. But there were two questions. First, the child table is still created but is not referenced in the parent table. Second, realm.createObject (Child.class); works, which generates unnecessary values ​​and enters the parent table. `Can a parent table relationship be created even if the child table is created later?` – hanmolee Mar 26 '18 at 15:06
  • Course it can, but you have to build your relationships between objects yourself. – EpicPandaForce Mar 26 '18 at 15:12
  • It seems to have solved it. When creating a child, we explicitly added the relationship to parent. thanks!! – hanmolee Mar 27 '18 at 03:28
0

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

}

insert Parent data

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)

}

insert Child data

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)
    }
}
  • problem solving

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

my example code : enter link description here

hanmolee
  • 253
  • 3
  • 9