ObjectBox[二] 教程:如何开始使用ObjectBox
ObjectBox[六] 数据监听和RX(Data Observers and Reactive Extensions)
ObjectBox[七] 支持LiveData(Android体系结构组件)
ObjectBox[十二] Meta Model, IDs, and UIDs
和SQLite这样的关系数据库不同,ObjectBox不需要你创建数据库模型。这并不意味着ObjectBox没有模型。出于效率原因,ObjectBox管理存储数据的Meta Model。这个Meta Model实际上就是ObjectBox的模型。它包括已知的对象类型,包括所有属性,索引等。和关系数据库主要的区别是ObjectBox会自动的管理模型。在某些情况下,它需要你来维护。这就是为什么会有这篇文章。
IDs
在ObjectBox Meta Model中,所有东西都有一个ID和一个UID。在ObjectBox内部使用ID来引用实体,属性和索引。例如,您有一个具有id
和name
属性的实体类User
。在Meta Model中,User
的ID 可能是42,并且id
的ID 是1,name
的ID是2。属性ID在实体类中是唯一的。
注意:不要将对象ID与Meta Model ID混淆:对象ID是@Id
注解属性的值。对象是Meta Model 中实体类(有一个唯一ID)的实例。
ObjectBox按顺序创建Meta Model ID(1,2,3,4,…)并记录最后的ID以防止ID冲突。
UIDs
根据经验,对于每个ID都有一个对应的UID。它们辅助ID,通常组合使用(例如在JSON文件中)。当ID被顺序分配时,UID是一个随机的长整型值。UID的工作是检测和解决Meta Model的并发性问题。
UID在实体,属性,索引等方面都是唯一的。因此,与ID不同,已经用于实体的UID不能用于属性。为了避免产生问题,ObjectBox会跟踪“退休”的UID,以确保以前使用但现在被遗弃的UID不会用于新的实体,属性,索引等。
IDs 的Json配置
ObjectBox将Meta Model的一部分存储在JSON文件中。这个文件提供给每个开发人员,因此应该保存版本控制系统(例如git)中。此JSON文件的主要目的是确保多个开发者修改ObjectBox Meta Model 的正确性。
这个JSON文件存储在文件objectbox-models / default.json中。例如,查看ObjectBox示例项目中的文件 :
{
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
"entities": [
{
"id": "1:6645479796472661392",
"lastPropertyId": "4:1260602348787983453",
"name": "Note",
"properties": [
{
"id": "1:9211738071025439652",
"name": "id"
},
{
"id": "2:8804670454579230281",
"name": "text"
},
{
"id": "3:6707341922395832766",
"name": "comment"
},
{
"id": "4:1260602348787983453",
"name": "date"
}
]
}
],
"lastEntityId": "1:6645479796472661392",
"lastIndexId": "0:0",
"lastSequenceId": "0:0",
"modelVersion": 2,
"retiredEntityUids": [],
"retiredIndexUids": [],
"retiredPropertyUids": [],
"version": 1
}
正如你所看到的,“id”属性使用冒号来结合ID和UID。这可以防止错误的合并。将元模型应用于数据库时,ObjectBox将检查ID和UID的正确性。
同步修改Meta Model
在编译时,ObjectBox从实体(@Entity
)类和JSON文件收集Model信息。完整的Model信息被写入生成的类 MyObjectBox
。
然后,在运行时,缓存在MyObjectBox
中的Model 和ObjectBox
数据库(文件)中的Model 同步。UID是使Model 与数据库同步的主键。同步涉及到一致性检查,当您尝试应用非法的meta 数据时可能会失败。
使用UID重命名
在某些时候,你可能想重命名一个实体类或只是一个属性。如果没有更多信息,ObjectBox将删除旧的实体/属性,并添加一个新的名称。这实际上是一个有效的场景:删除一个属性并添加另一个属性。当然,如果你需要重命名,那么就需要使用UID。
添加一个 没有值的 @ UID
注解到你想要重命名的实体或属性,并开始编译。编译将失败,并提示您重命名需要用到的UID。请查看ObjectBox[九] 数据模型变更。
解决模型冲突
在关于UID的部分,我们已经暗示了Model冲突的可能性。这是由开发人员同时更改Model导致的,通常是通过添加实体或属性。最后的例子帮助我们手动解决冲突。
关注点
在最初的开发过程中,可能会删除Model和所有数据库。这将导致Model重新开始,例如所有UID将被重新生成。应该按照如下顺序来生成:
- 删除JSON文件(objectbox-models / default.json)
- 编译以从头开始生成新的JSON文件
- 将重新创建的JSON文件提交到您的VCS(例如git)
- 删除所有以前创建的ObjectBox数据库(对于Android,例如删除应用程序的数据或卸载应用程序)
虽然这是一个简单的方法,但它有明显的缺点,就是应用程序不能升级。
陷阱:如果数据库文件没有被删除,请检查 Android manifest中 application
是否存在 android:allowBackup = "true"
。备份可能会重新生成旧文件,应该设置android:allowBackup = "false"
或删除语句。
手动解决冲突
通常,最好按照以下步骤编辑JSON文件来解决冲突并修复Model:
- 确保ID是唯一的:在JSON文件中,id属性的格式为“ID:UID”。如果您在Git合并后有重复的ID,则应该为其中的一个分配新的ID(保留UID部分!)。通常,新ID将是“上次使用的ID + 1”。
- 更新最后的ID值: 对于实体,更新
lastEntityId
; 对于属性,更新lastPropertyId
- 检查其他ID索引:对UID进行文本搜索,并检查UID对应的ID是否错误。
举一个例子来说明这一点,考虑最后分配的实体ID是41.因此,下一个实体ID将是42.现在,开发者Alice和Bob彼此不知道对方添加新实体。Alice添加一个新的实体Ant
,它被分配实体ID 42.同时,Bob也添加一个新实体Bear
,也被分配了ID 42。在两个开发者提交他们的代码之后,ID 42不是唯一的标识一个实体类型(Ant
还是Bear
?)。此外,在Alice的ObjectBox中,实体ID 42已经指向了Ant
,而Bob的ObjectBox 实体ID指向了42到Bear
。这种情况需要使用UID来解决。比方说Alice这边Ant
的UID是12345,Bob这边Bear
的UID是9876。现在,当Bob更新到Alice的提交后,他需要解决冲突。手动将实体ID 43分配给Bear
,并相应地将lastEntityId
属性更新为"43:9876"
(ID:UID)。在Bob提交他的更改后,两个开发人员都可以继续使用ObjectBox。