Hi all. I am using data class for my database enti...
# getting-started
g
Hi all. I am using data class for my database entities. I have a parent child relationship, where child has a reference to a parent and a parent has a collection of its children. So a parent references a child and the child references the parent. A circular reference. How to create parent and child, taking into account that they are immutable?
r
You could work around it with something like this:
Copy code
data class Parent(val children: List<Child>)
data class Child(val parent: Parent)

val children = mutableListOf<Child>()
val parent = Parent(children)
repeat(10) {
    children += Child(parent)
}
but it's a bit hacky. You may want to rethink your data structure.
❤️ 1
g
@Ruckus rethink, but how? My database entity has a reference to a parent (foreign key).
r
Usually in such cases, I first look at the initial requirement e.g. "where child has a reference to a parent and a parent has a collection of its children". Why is that the case? Often with a circular dependency like that, only one of the two references is actually a "requirement", and the other is a "nice to have" that can either be maintained separately or be in a "front end only" field on the data class (that isn't part of the data specification)
g
Btw. Thanks a lot for the code snippet btw. I think I got it. So Parent has a list of children. I create a parent with an empty list and then add children there. Thank you so much.
r
For example, either
Copy code
data class Parent {
    val children = mutableListOf<Children>()
}
data class Child(val parent: Parent)
or
Copy code
data class Parent(val children: List<Child>)
data class Child {
    lateinit var parent: Parent
}
g
Well, if I look at my database structure. The parent column is nullable. Btw parent and child is the same entity represented by the same type in the application code.
Could you advise anything to read on the topic? Books, etc?
r
Without knowing how the data is used, I would probably include the parent property, and maintain the children collection separately. That could be in a separate "children" property on the class that isn't part of the data spec, or (as often tends to be useful for me) in a completely separate
val children = mutableMapOf<Thing: MutableList<Thing>>()
, as I find the children collection is often used in one particular place in the app and so maintaining it for the entire app is a waste (and tends to bite me later), but again, that entirely depends on your use case. > Could you advise anything to read on the topic? Books, etc? I can't think of anything off the top of my head. This is based on my own experience, so take it with the usual grain of salt. In my experience, the parent reference is often useful from a functionality standpoint, whereas the tree decedent structure if often just for display purposes, in which case a separate map is great, or more likely just the generic class provided by your graphics library for displaying tree content.
If the tree structure it more valuable to your use case, basically just invert everything I just said 🙂
g
Thanks a lot. Very interesting read.
g
You could start with one of the links empty and then create a changed version (
.copy()
) that contains the second link.
g
@Goetz Markgraf Immutable properties do not work for circular references:
Copy code
parent = Parent()
child = Child(parent)
parent.copy(child = child)
The child of the parent has a link to the old parent without children, not the new one. For circular references some form of mutability is required. See options in previous replies.
g
Sorry, you‘re absolutely right
g
hi all. I finally went back to implement this in my code. I got this result:
Copy code
data class Entity(val name, val parent: Entity?, var children: List<Entity>?)
1.
parent
and
children
is a part of the data class because I want to
copy()
them 2. I must override
equals()
,
hashCode()
and
toString()
otherwise I get stack overflow error.