当前位置: 首页 > news >正文

短视频直播系统,关于数据关系的正确认知 - 云豹科技

短视频直播系统,关于数据关系的正确认知

设计一个关系型数据库很重要的一部分是将数据拆分成具有相关关系的数据表,然后将数据以符合这种关系的逻辑方式整合到一起。从 Room 2.2 的稳定版开始,我们可利用一个 @Relation 注解来支持表之间所有可能出现的关系: 一对一、一对多和多对多。

一对一关系

image

 

假设我们生活在一个每个人只能拥有一只狗,且每只狗只能有一个主人的 “悲惨世界” 中,这就是一对一关系。如果要以关系型数据库的方式来反应它的话,我们可以创建两张表: Dog 表和 Owner 表,其中 Dog 表通过 owner id 来引用 Owner 表中的数据,或者 Owner 表通过 dog id 来引用 Dog 表中的数据。

@Entity
data class Dog(@PrimaryKey val dogId: Long,val dogOwnerId: Long,val name: String,val cuteness: Int,val barkVolume: Int,val breed: String
)@Entity
data class Owner(@PrimaryKey val ownerId: Long, val name: String)

假设我们想在一个列表中展示所有的狗和它们的主人,我们需要创建一个 DogAndOwner 类:

data class DogAndOwner(val owner: Owner,val dog: Dog
)

为了在 SQLite 中进行查询,我们需要 1) 运行两个查询: 一个获取所有的主人数据,一个获取所有的狗狗数据,2) 根据 owner id 来进行数据的关系映射。

SELECT * FROM OwnerSELECT * FROM Dog WHERE dogOwnerId IN (ownerId1, ownerId2, …)

要在 Room 中获取一个 List ,我们不需要自己去实现上面说的查询和映射,只需要使用 @Relation 注解。

在我们的示例中,由于 Dog 有了 owner 的信息,我们给 dog 变量增加 @Relation 注解,指定父级 (这里对应 Owner) 上的 ownerId 列对应 dogOwnerId:

data class DogAndOwner(@Embedded val owner: Owner,@Relation(parentColumn = "ownerId",entityColumn = "dogOwnerId")val dog: Dog
)

现在我们的 Dao 类可被简化成:

@Transaction
@Query("SELECT * FROM Owner")fun getDogsAndOwners(): List<DogAndOwner>

注意: 由于 Room 会默默的帮我们运行两个查询请求,因此需要增加 @Transaction 注解来确保这个行为是原子性的。

一对多关系

image

 

再假设,一个主人可以养多只狗狗,现在上面的关系就变成了一对多关系。我们之前定义的数据库 schema 并不需要改变,仍然使用同样的表结构,因为在 “多” 这一方的表中已经有了关联键。

现在,要展示狗和主人的列表,我们需要创建一个新的类来进行建模:

data class OwnerWithDogs(val owner: Owner,val dogs: List<Dog>
)

为了避免运行两个独立的查询,我们可以在 Dog 和 Owner 中定义一对多的关系,同样,还是在 List 前增加 @Relation 注解。

data class OwnerWithDogs(@Embedded val owner: Owner,@Relation(parentColumn = "ownerId",entityColumn = "dogOwnerId")val dogs: List<Dog>
)

现在,Dao 类又变成了这样:

@Transaction
@Query("SELECT * FROM Owner")fun getDogsAndOwners(): List<OwnerWithDogs>

多对多关系

image

 

现在,继续假设我们生活在一个完美的世界中,一个人可以拥有多只狗,每只狗可以拥有多个主人。要对这个关系进行映射,之前的 Dog 和 Owner 表是不够的。由于一只狗狗可以有多个主人,我们需要在同一个 dog id 上能够匹配多个不同的 owner id。由于 dogId 是 Dog 表的主键,我们不能直接在 Dog 表中添加同样 id 的多条数据。为了解决这个问题,我们需要创建一个 associative 表 (也被称为连接表),这个表来存储 (dogId, ownerId) 的数据对。

@Entity(primaryKeys = ["dogId", "ownerId"])
data class DogOwnerCrossRef(val dogId: Long,val ownerId: Long
)

如果现在我们想要获取到所有的狗狗和主人的数据,也就是 List,仅需要编写两个 SQLite 查询,一个获取到所有的主人数据,另一个获取 Dog 和 DogOwnerCrossRef 表的连接数据。

SELECT * FROM Owner
SELECTDog.dogId AS dogId,Dog.dogOwnerId AS dogOwnerId,Dog.name AS name,_junction.ownerId
FROMDogOwnerCrossRef AS _junction
INNER JOIN Dog ON (_junction.dogId = Dog.dogId)
WHERE _junction.ownerId IN (ownerId1, ownerId2, …)

要通过 Room 来实现这个功能,我们需要更新 OwnerWithDogs 数据类,并告诉 Room 要使用 DogOwnerCrossRef 这个连接表来获取 Dogs 数据。我们通过使用 Junction 引用这张表。

data class OwnerWithDogs(@Embedded val owner: Owner,@Relation(parentColumn = "ownerId",entityColumn = "dogId",associateBy = Junction(DogOwnerCrossRef::class))val dogs: List<Dog>
)

在我们的 Dao 中,我们需要从 Owners 中选择并返回正确的数据类:

@Transaction
@Query("SELECT * FROM Owner")fun getOwnersWithDogs(): List<OwnerWithDogs>

更高阶的数据库关系用例

当使用 @Relation 注解时,Room 会默认从所修饰的属性类型推断出要使用的数据库实体。例如,到目前为止我们用 @Relation 修饰了 Dog (或者是 List),Room 就会知道如何去对该类进行建模,以及知道要查询的到底是哪一行数据。

如果您想让该查询返回一个不同的类,比如 Pup 这样不是一个数据库实体但是包含了一些字段的对象。我们可以在 @Relation 注解中指定要使用的数据库实体:

data class Pup(val name: String,val cuteness: Int = 11
)
data class OwnerWithPups(@Embedded val owner: Owner,@Relation(parentColumn = "ownerId",entity = Dog::class,entityColumn = "dogOwnerId")val dogs: List<Pup>
)

如果我们只想从数据库实体中返回特定的列,您需要通过在 @Relation 中的 projection 属性中定义要返回哪些列。例如,假如我们只想获取 OwnerWithDogs 数据类中所有狗的名字,由于我们需要用到 List,Room 不能推断出这些字符串是对应于狗的品种呢还是狗的名字,因此我们需要在 projection 属性中指名。

data class OwnerWithDogs(@Embedded val owner: Owner,@Relation(parentColumn = "ownerId",entity = Dog::class,entityColumn = "dogOwnerId",projection = ["name"])val dogNames: List<String>
)

如果您想在 dogOwnerId 和 ownerId 中定义更严格的关系,而不管您所创建的是什么,您可以通过在字段中使用 ForeignKey 来做到。记住,SQLite 中的外键 会创建索引,并且会在更新或者删除表中数据时做级联操作。因此您要根据实际情况来判断是否使用外键功能。

不管您是要使用一对一,一对多还是多对多关系,Room 都会为您提供 @Relation 注解来解决问题。您可以在我们的 Android Dev Summit ’19 的一个 演讲 中了解有关 Room 2.2 的更多新功能。

以上就是短视频直播系统,关于数据关系的正确认知, 更多内容欢迎关注之后的文章

http://www.jsqmd.com/news/63673/

相关文章:

  • 2025 年 12 月立体车库厂家权威推荐榜:智能升降/循环式/机械停车库,空间革新与高效存取解决方案深度解析
  • 家装到底该选哪家?2025年最新市场洞察与一家国企背景综合服务商的深度案例推荐
  • 2025年耐用的6通道测力称重工业型变送器厂家最新推荐排行榜
  • 2026 北京市律师哪家好?权威测评排行榜:5 家机构实力与解决方案解析
  • 2025年质量好的循环式提升机/托盘提升机厂家推荐及选购指南
  • 北京知名律所推荐 2026:整体大排名 TOP5,高性价比机构名单
  • 2025年新能源汽车升级排名及软件升级推荐,看看哪家专业可靠
  • 2025年热门的起重机减速机最新TOP品牌厂家排行
  • 2025年河南靠谱污水检查井供应商推荐,专业矩形检查井生产厂
  • AiStudio才是Gemini模型的编程真身!
  • 广东惠算GEO:实现零点击获客的AI优化引领者
  • 随钻测井中的高温定向传感:原理、进展与行业影响
  • 2025年知名的中空板厂家最新权威实力榜
  • NOIP 总结
  • 2025年靠谱的净化铝材/圆弧净化铝材实力厂家TOP推荐榜
  • 2025年评价高的异型管缩管机。热门厂家推荐榜单
  • 2025年评价高的不锈钢三节轨厂家最新热销排行
  • 从 ArrayListint 报错这个现象出发,串联起 Java 基础
  • 2026 北京离婚财产律师推荐名单:靠谱机构 VS 精品律所,公正评价性价比之选
  • 2025年质量好的拖拉机圆盘耙厂家推荐及选择参考
  • 2025年知名的耐铬酸涂层厂家最新实力排行
  • 2026 北京擅长打离婚官司的律所排名:5 家靠谱机构解析,高胜诉率诉讼方案推荐
  • 2025年热门的食品级转子泵厂家最新实力排行
  • 2025年度上海圆锯机品牌排名:宏萌圆锯机的交货期长吗?
  • 2026年河北石家庄赵县农村自建房推荐榜,图南建房宝领衔 六家实力公司赋能乡村宜居生活
  • 惠州惠算GEO:自研AI搜索优化,多平台覆盖,转化快本地服务
  • 2025年评价高的伺服减速器/齿轮减速器用户口碑最好的厂家榜
  • 想在赵县老家盖房子,靠谱的自建房公司口碑推荐。河北石家庄赵县自建房公司/机构权威测评推荐排行榜。
  • 2025年质量好的商业动画制作/工业产品动画制作高评分推荐榜单
  • 2026年河北衡水景县农村自建房推荐榜,图南建房宝领衔 六家实力公司赋能乡村宜居生活