除了一对多的关联方式以外,资料和资料间也有可能是多对多的关联方式。
比方说常见的用户标签(tag) 系统,就是一种多对多的关联:每个标签可能对应多个用户,而每个用户也可能被标记上多个不同标签。
要怎麽设计这样的关联呢?我们一起来看看
多对多关系的处理方式,比较建议的做法是设计一个中间表,每笔资料纪录
比方说,如果我们的资料是
user |
tag |
---|---|
Alice | admin, registered, author |
Bob | customer, unregistered |
Carol | customer, registered, reader |
那我们的资料表内容可能会是
user |
|
---|---|
id |
name |
1 | Alice |
2 | Bob |
3 | Carol |
tag |
|
---|---|
id |
name |
1 | admin |
2 | registered |
3 | author |
4 | customer |
5 | unregistered |
6 | reader |
user_tag |
|
---|---|
user_id |
tag_id |
1 | 1 |
1 | 2 |
1 | 3 |
2 | 4 |
2 | 5 |
3 | 4 |
3 | 2 |
3 | 6 |
假设我们需要的用户标签系统,tag
资料表和 DAO 物件如下
object Tags : IntIdTable() {
val name = varchar("name", 50)
}
class Tag(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Tag>(Tags)
var name by Tags.name
}
我们定义中间表 user_tag
如下
object UserTag : IntIdTable() {
val user = reference("user", Users)
val tag = reference("tag", Tags)
}
利用 via
这个内缀,我们让 user
和 tag
物件与 UserTag
资料表进行关联
class Tag(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<Tag>(Tags)
var name by Tags.name
var users by User via UsersTags
}
class User(id: EntityID<Int>) : IntEntity(id) {
companion object : IntEntityClass<User>(Users)
var name by Users.name
var tags by Tag via UsersTags
}
并且定义 user
和 tag
内容
SchemaUtils.create(Users)
SchemaUtils.create(Tags)
val alice = User.new {
name = "Alice"
}
val bob = User.new {
name = "Bob"
}
val carol = User.new {
name = "Carol"
}
val admin = Tag.new {
name = "admin"
}
val registered = Tag.new {
name = "registered"
}
val author = Tag.new {
name = "author"
}
val customer = Tag.new {
name = "customer"
}
val unregistered = Tag.new {
name = "unregistered"
}
val reader = Tag.new {
name = "reader"
}
定义完成之後,我们就可以以 DAO 的方式,进行 user
和 tag
的关联了
alice.tags = SizedCollection(listOf(admin, registered, author))
bob.tags = SizedCollection(listOf(customer, unregistered))
carol.tags = SizedCollection(listOf(customer, registered, reader))
定义完成之後,我们可以透过 user
来找到所有对应的 tag
carol.tags.forEach { println("tag: ${it.name}") }
上面这段程序码会印出
tag: customer
tag: registered
tag: reader
我们也可以透过 tag
来找到对应的 user
registered.users.forEach { println("user: ${it.name}") }
上面这段程序码会印出
user: Alice
user: Carol
透过 DAO 的方式,以物件的思维,来实作多对多的资料关联语法,个人认为比起透过 query 关联的方式来说,更加直观并且好操作许多。
关於技术选择 可以先决定也可以题目订了後再看要用什麽 我们因为想顺便学一些比较就业取向的技术 所以就...
Hash Table是一种有key value的资料结构~ 我们能在Hash Table中存入一个v...
今天要跟大家讲讲TypeScript(TS)的命名空间(Namespace), 命名空间(Names...
恩,标题不知道怎麽下成中文 在之前的范例里,示范了如何用coroutine做一次性的网路请求,并交结...
逐格动画Frame Animation 最早期的动画制作方式,使用不同的图片连续拨放 先将图片放入专...