我不断发现使用像这样的对象数据库非常令人困惑的一件事 数据库4o 这就是您应该如何处理通常由 SQL/PL-SQL 处理的复杂迁移。

例如,假设您在关系数据库中有一个名为 my_users 的表。最初您有一个名为“full_name”的列,现在您的软件处于 V2 版本,您希望删除此列,将全名拆分在空格上,并将第一部分放入名为“first_name”的列中,将第二部分放入名为“first_name”的列中名为姓氏。在 SQL 中,我只需填充“first_name”和“second_name”列,然后删除名为“full_name”的原始列。

我该如何在 db4o 这样的东西中做到这一点?我是否编写了一个 Java 程序,通过脚本查找 User.class 的所有对象,在设置first_name 和last_name 时将full_name 设置为null?当我进行下一次 svn 提交时,将没有与 full_name 对应的字段/bean 属性,这会是一个问题吗?似乎要在我的“架构”发生变化的生产应用程序中使用它,我想编写一个脚本将数据从版本 x 迁移到版本 x+1,然后在版本 x+2 中实际上删除我试图删除的属性摆脱版本 x+1,因为我无法编写 Java 脚本来修改不再属于我的类型的属性。

看来问题的一部分是 RDBMS 根据一个简单的不区分大小写的基于字符串的名称来解析您所引用的对象,在像 Java 这样的语言中,打字比这更复杂,如果 getter 则无法引用属性/setter/field 不是运行时加载的类的成员,因此您本质上需要在同一个脚本中拥有 2 个版本的代码(嗯,自定义类加载器听起来很痛苦),存储的类的新版本属于另一个包(听起来很乱),或者使用我提到的版本 x+1 x+2 策略(需要更多的规划)。也许有一些我从未从 db4o 文档中收集到的明显解决方案。

有任何想法吗?希望这有一定道理。

有帮助吗?

解决方案

首先,db4o 处理“简单” 自动添加或删除字段等场景. 。添加字段时,所有现有对象都会存储默认值。当您删除字段时,现有对象的数据仍在数据库中,您仍然可以访问它。重命名字段等是 特殊的“重构”调用.

现在你的场景你会做这样的事情:

  1. 删除字段“full_name”,添加新字段“first_name”和“second_name”
  2. 迭代所有“地址”对象
  3. 通过“StoredClass”-API 访问旧字段
  4. 拆分、更改、更新等值。在新字段上设置新值并存储对象。

假设我们有一个“地址”类。“全名”字段已被删除。现在我们不想将其复制到“名字”和“姓氏”。然后它可以像这样(Java):

    ObjectSet<Address> addresses = db.query(Address.class);
    StoredField metaInfoOfField = db.ext().storedClass(Address.class).storedField("full_name", String.class);
    for (Address address : addresses) {
        String fullName = (String)metaInfoOfField.get(address);
        String[] splitName = fullName.split(" ");
        address.setFirstname(splitName[0]);
        address.setSurname(splitName[1]);
        db.store(address);
    }

正如您所建议的,您将为每个版本更新编写迁移代码。如果字段不再是您的类的一部分,您必须使用上面的“StoredField”-API 来访问它。

您可以使用以下命令获取所有“存储”类的列表 ObjectContainer.ext().storedClasses(). 。和 StoredClass.getStoredFields() 您可以获得所有商店字段的列表,无论您的班级中不再存在该字段。如果某个类不再存在,您仍然可以获取对象并通过“GenericObject”类访问它。

更新:对于数据库需要通过多个版本步骤进行迁移的更复杂的场景。

例如,在版本 v3 中,地址对象看起来完全不同。因此,v1 到 v2 的“迁移脚本”不再获得所需的字段(在我的示例中是名字和姓氏)。我认为处理这个问题有多种可能性。

  1. (假设 Java 支持这个想法。当然.NET 中也有类似的东西)。您可以将迁移步骤设为 Groovy 脚本. 。因此每个脚本都不会干扰另一个脚本。然后,您可以在那里定义迁移所需的类。所以每个迁移都有自己的迁移类。和 别名 您可以将 groovy-migration-classes 绑定到实际的 java-classes。
  2. 为复杂场景创建重构类。还将此类绑定到 别名.

其他提示

我正在有点狂射的这里,因为我没有在我的生活中重构数据太多。

您正在做一个比较奇怪:如果你想“热迁移”的分贝,你可能必须做你所描述的x+1x+2版本的做法,但我真的不知道 - 我不会”知道如何做到这一点与SQL要么因为我不是一个数据库专家。

如果您要迁移“冷”,但是,你可能只是做一步就通过实例从旧数据的新对象,存储新对象,删除旧的对象在存储中的每个对象。请参见的db4o参考

不过说实话:在RDBMS同样的过程是复杂的,也因为你将不得不取消激活约束检查(也可能触发等),实际执行的操作 - 在您所提供的例子也许不是,但对于大多数现实世界的情况。毕竟,字符串分割是很容易将有小的增益。

  

在SQL我想简单地填充 “如first_name” 和 “SECOND_NAME” 列

是,用的简单的字符串分割操作,你可以的只是的做到这一点。但基于大而复杂的规则集,它可能在SQL中简单地表示在一个典型的重构方案,您正在重新构造的对象,可能需要复杂的计算,或外部数据源。

要做到这一点,你必须编写代码了。

毕竟,我没有看到在这两个过程中差别太大。你永远要小心使用实时数据,你肯定会做一个备份,在这两种情况下。重构很有趣,但持久性是棘手所以同步是在任何情况下一个挑战。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top