之前我們看過了透過 DAO 方式,來處理資料之間呈現一對多關聯,或者多對多關聯的做法。
今天我們來看看,如果資料是呈現 Parent-Child reference 時,我們該怎麼利用 Exposed 框架處理
根據官方文件的說法
Parent-child reference is very similar to many-to-many version, but an intermediate table contains both references to the same table.
簡單的說,其實就是資料的多對多關係,只是關聯的對象變成了同一類別的內容而已。
比方說,之前我們提到多對多關係時,使用的範例是 user
和 tag
。如果我們想要建立的,是 user
和 user
之間的多對多關係,那就變成得用 Parent-Child reference 來處理了。
我們用以下的方式來調整 user
資料表和 DAO 物件
object Users : IntIdTable() {
val name = varchar("name", 50)
}
object UsersToUsers : Table() {
val parent = reference("parent_user_id", Users)
val child = reference("child_user_id", Users)
}
class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)
var name by Users.name
var parents by User.via(UsersToUsers.child, UsersToUsers.parent)
var children by User.via(UsersToUsers.parent, UsersToUsers.child)
}
類似多對多關係時所使用的中間表,我們藉由宣告 UsersToUsers
中間表,來記錄 User
之間的關聯。
宣告之後,我們就可以用物件的邏輯,來記錄每個 user
對應的 parents
和 children
了
SchemaUtils.create(Users)
SchemaUtils.create(UsersToUsers)
val alice = User.new {
name = "Alice"
}
val bob = User.new {
name = "Bob"
}
val carol = User.new {
name = "Carol"
}
bob.parents = SizedCollection(listOf(alice))
carol.parents = SizedCollection(listOf(alice, bob))
這樣宣告後,我們可以取出紀錄的 parents
關聯,比方說
carol.parents.forEach { println(it.name) }
這樣會取得
Alice
Bob
除了可以透過 bob
和 carol
取得對應的 parents
,還可以反過來透過 alice
物件找出對應的 children
有哪些
alice.children.forEach { println(it.name) }
這樣會取得
Bob
Carol
利用 Parent-Child reference 的方式,我們可以用更加直覺的寫法,來實現資料之間的關聯。進而可以透過資料庫,來紀錄樹狀結構的資料呈現。