ObjectBox数据库实体类重命名或修改字段解决方案

205 阅读7分钟

数据模型更新

2024年6月27日14:49:07 ObjectBox - 数据模型更新

  • UIDs
  • 重命名实体和属性
    • Java/Kotlin和Dart的操作方法与示例
    • Python的操作方法与示例
  • 更改属性类型
    • 操作方法与示例

数据模型更新

如何在ObjectBox中重命名实体和属性、更改属性类型。 ObjectBox - 数据模型更新 ObjectBox主要自动管理其数据模型(模式)。数据模型由你定义的实体类来定义。当你添加或删除实体或实体的属性时,ObjectBox会处理这些更改,无需你采取进一步行动。 对于其他更改,如重命名或更改类型,ObjectBox需要额外信息来使事情明确。这是通过设置唯一ID(UIDs)作为注释来完成的,如下所示。

UIDs

ObjectBox通过为实体和属性分配唯一ID(UIDs)来跟踪它们。所有这些UIDs都存储在一个文件中,对于Java和Kotlin是“objectbox-models/default.json”,对于Dart是“lib/objectbox-model.json”,你应该将其添加到版本控制系统(例如git)中。如果你感兴趣,我们有关于UIDs和概念的详细文档。但让我们继续了解如何重命名实体或属性。 简而言之:要进行与UID相关的更改,在实体或属性上添加“@Uid”注释(Java、Kotlin)或“@Entity(uid: 0)/@Property(uid: 0)”(Dart),然后构建项目以获取进一步的说明。对要更改的每个实体或属性重复此操作。

重命名实体和属性

那么为什么我们需要那个UID注释呢?如果你只是重命名一个实体类,ObjectBox只会看到旧实体消失了,而有一个新实体可用。这可以有两种解释:

  1. 旧实体被删除,应添加一个新实体,旧数据被丢弃。这是ObjectBox的默认行为。
  2. 实体被重命名,旧数据应被重新使用。 所以要告诉ObjectBox进行重命名而不是丢弃旧实体和数据,你需要确保它知道这是同一个实体而不是一个新实体。你通过将内部UID附加到实体上来做到这一点。 对于属性也是如此。 现在让我们逐步了解如何做到这一点。如果你想重命名一个属性,过程是相同的:

Java/Kotlin和Dart的操作方法与示例

步骤1:向要重命名的实体/属性添加一个空UID: Java/Kotlin:

@Entity
@Uid
public class MyName {... }

Dart:

@Entity(uid: 0)
class MyName {... }

步骤2:构建项目(在Dart中,运行“pub run build_runner build”)。构建将失败,并显示一条错误消息,其中给出了实体/属性的当前UID: Java/Kotlin:

error: [ObjectBox] UID操作对于实体"MyName":
[重命名]使用@Uid(6645479796472661392L)应用当前UID -
[更改/重置]使用@Uid(4385203238808477712L)应用新UID
在"MyName"上找到@Entity(uid: 0) - 你可以选择以下操作之一:
    [重命名]使用@Entity(uid: 6645479796472661392)应用当前UID
    [更改/重置]使用@Entity(uid: 4385203238808477712)应用新UID

Dart:

error: [ObjectBox] UID操作对于实体"MyName":
[重命名]使用@Entity(uid: 6645479796472661392)应用当前UID -
[更改/重置]使用@Entity(uid: 4385203238808477712)应用新UID
在"MyName"上找到@Entity(uid: 0) - 你可以选择以下操作之一:
    [重命名]使用@Entity(uid: 6645479796472661392)应用当前UID
    [更改/重置]使用@Entity(uid: 4385203238808477712)应用新UID

步骤3:将错误消息中[重命名]部分的UID应用于你的实体/属性: Java/Kotlin:

@Entity
@Uid(6645479796472661392L)
public class MyName {... }

Dart:

@Entity(uid: 6645479796472661392)
class MyName {... }

步骤4:最后要做的是在语言级别进行实际重命名(Java、Kotlin等): Java/Kotlin:

@Entity
@Uid(6645479796472661392L)
public class MyNewName {... }

Dart:

@Entity(uid: 6645479796472661392)
class MyNewName {... }

步骤5:再次构建项目,现在应该成功。你现在可以按预期使用重命名后的实体/属性,并且所有现有数据仍将存在。 重复上述步骤以重命名另一个实体或属性。 注意:你也可以在引言中提到的模型JSON中找到实体/属性的UID,而不是执行上述操作。在重命名实体/属性之前,你可以自己将UID值添加到注释中,并跳过ObjectBox为你打印UID的中间错误。在重命名多个属性时,这可能会更快。

Python的操作方法与示例

由于在Python中没有构建步骤,重命名实体的步骤不同。假设我们要将实体“MyName”重命名为“MyNewName”:

@Entity()
class MyName:
    id = Id
    some_property = Int

步骤1:找出实体“MyName”的UID:

print(MyName._uid)
# 6645479796472661392

步骤2:将“MyName”重命名为“MyNewName”并显式指定旧UID:

@Entity(uid=6645479796472661392)
class MyNewName:
    id = Id
    some_property = Int

这使得Objectbox能够将旧实体与新实体关联起来,并保留持久化数据。如果你不指定旧UID,Objectbox将丢弃旧数据,并向模式中添加一个名为“MyNameName”的全新实体。

更改属性类型

ObjectBox不支持将现有属性数据迁移到新类型。你必须自己处理此问题,例如,保留旧属性并添加一些迁移逻辑。 更改属性类型有两种解决方案:

  1. 添加一个具有不同名称的新属性(仅当属性尚未有“@Uid”注释时才有效):
// 旧:
String year;
// 新:
int yearInt;
  1. 为属性设置一个新UID,以便ObjectBox将其视为新属性。让我们逐步了解如何做到这一点:

操作方法与示例

步骤1:向要更改类型的属性添加“@Uid”注释: Java/Kotlin:

@Uid
String year;

Dart:

@Property(uid: 0)
String year;

步骤2:构建项目。构建将失败,并显示一条错误消息,其中给出了新创建的UID值: Java/Kotlin:

error: [ObjectBox] UID操作对于属性"MyEntity.year":
[重命名]使用@Uid(6707341922395832766L)应用当前UID -
[更改/重置]使用@Uid(9204131405652381067L)应用新UID
在"year"上找到@Property(uid: 0) - 你可以选择以下操作之一:
    [重命名]使用@Property(uid: 6707341922395832766)应用当前UID
    [更改/重置]使用@Property(uid: 9204131405652381067)应用新UID

Dart:

error: [ObjectBox] UID操作对于属性"MyEntity.year":
[重命名]使用@Property(uid: 6707341922395832766)应用当前UID -
[更改/重置]使用@Property(uid: 9204131405652381067)应用新UID
在"year"上找到@Property(uid: 0) - 你可以选择以下操作之一:
    [重命名]使用@Property(uid: 6707341922395832766)应用当前UID
    [更改/重置]使用@Property(uid: 9204131405652381067)应用新UID

步骤3:将[更改/重置]部分的UID应用于你的属性: Java/Kotlin:

@Uid(9204131405652381067L)
int year;

Dart:

@Property(uid: 9204131405652381067)
String year;

步骤4:再次构建项目,现在应该成功。你现在可以在实体中使用该属性,就像它是一个新属性一样。 重复上述步骤以更改另一个属性的类型。