android - Room 数据库中的@ForeignKey 和@Relation 注释有什么区别?
问题描述
我无法理解这些注释之间的区别。在我的用例中,我想在表之间创建一对多的关系。并找到了两种选择:一种使用@ForeignKey,另一种使用@Relation
我还发现,如果我更新该行(例如使用 OnCoflictStrategy.Replace),我将丢失该行的外键,这是真的吗?
解决方案
@ForeignKey定义了一个约束(又名规则),该约束要求子列存在于父列中。如果尝试破坏该规则,则会发生冲突(可以通过 onDelete/onUpdate 定义以各种方式处理)。
@Relationship用于定义在父对象中返回多个子对象(可能是外键子对象)的关系。
在这一切之下,@Relation自动(有效地)连接表并生成子对象的数量。虽然@ForeignKey只会影响架构(onDelete/onUpdate 处理除外),但它不会导致各个表被连接。
也许考虑以下几点:-
服务实体
@Entity(
tableName = "services"
)
class Services {
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "services_id")
var id: Long = 0
var service_date: String = ""
var user_mobile_no: String = ""
}
和
ServiceDetail 实体:-
@Entity(
tableName = "service_detail",
foreignKeys = [
ForeignKey(
entity = Services::class,
parentColumns = ["services_id"],
childColumns = ["services_id"],onDelete = ForeignKey.SET_DEFAULT
)
]
)
class ServiceDetail {
@PrimaryKey
var id: Long? = null;
var services_id: Long = 0;
@ColumnInfo(defaultValue = "1")
var service_type_id: Long = 0;
constructor()
@Ignore
constructor(services_id: Long, service_type_id: Long) {
this.services_id = services_id
this.service_type_id = service_type_id
}
}
- 这就是说,为了添加 ServiceDetail,services_id 列的值必须是存在于services表的services_id列中的值,否则会发生冲突。此外,如果从 services 表中删除了一行,则 service_detail 表中引用该行的任何行也将被删除(否则该行无法从 services 表中删除)。
现在考虑这个普通类(POJO),它不是一个实体(又名表):-
class ServiceWithDetail {
@Embedded
var services: Services? = null
@Relation(entity = ServiceDetail::class,parentColumn = "services_id",entityColumn = "services_id")
var serviceDetail: List<ServiceDetail>? = null
}
这大致是说当您请求 ServiceWithDetail 对象然后获取服务对象以及相关 service_detail 对象的列表时
你会有一个道,比如:-
@Query("SELECT * FROM services")
fun getAllServices() :List<ServiceWithDetail>
因此,它将从服务表中获取所有服务以及相关服务(即 services_detail 中的 services_id 与正在处理的当前服务行的 services_id 相同)。
冲突策略
REPLACE执行以下操作:-
当 UNIQUE 或 PRIMARY KEY 约束违规发生时,REPLACE 算法会在插入或更新当前行之前删除导致约束违规的预先存在的行,并且命令会继续正常执行。
如果发生 NOT NULL 约束冲突,则 REPLACE 冲突解决方案将 NULL 值替换为该列的默认值,或者如果该列没有默认值,则使用 ABORT 算法。如果发生 CHECK 约束或外键约束冲突,则 REPLACE 冲突解决算法的工作方式与 ABORT 类似。
当 REPLACE 冲突解决策略删除行以满足约束时,当且仅当启用递归触发器时,删除触发器才会触发。
对于由 REPLACE 冲突解决策略删除的行,不会调用更新挂钩。REPLACE 也不会增加更改计数器。本段中定义的异常行为可能会在未来的版本中发生变化。代替
因此,您所经历的行为的可能性。但是,这取决于更新在做什么。如果 ForeignKey(s) 的值不同,那么他们应该假设没有外键冲突,用新的有效值替换外键值。如果外键值不变,则替换行将具有相同的外键。
推荐阅读
- python - 如何从 python 3 的嵌套列表中删除多个项目?
- typescript - 如何在 Angular 7 的 ngx-dropzone-wrapper 中显示服务器上的现有文件
- excel - 每 2 周查找交易日期(如果是周六或周日,则显示周五日期)
- php - Codeception\Exception\InjectionException : 服务 di 未定义,无法从测试中访问
- graphql - 简单 GraphQL 模式的可能有效查询
- html - Angular 7根据对象键显示/隐藏表并根据对象值设置div
- r - R - 在“purrr”中的列表上递归应用函数,同时保留其结构
- java - 对于“操作”这个词,为什么 OpenNLP 程序返回类型为“NN”?
- powershell - 通过powershell脚本问题签署dll和exe文件
- linkedin - LinkedIn API:列出 UGC 帖子时出现服务器错误