ben*_*rre 8 db4o jdbc database-schema object-oriented-database
我不断发现使用像db4o这样的对象数据库非常困惑的一件事是你应该如何处理通常由SQL/PL-SQL处理的复杂迁移.
例如,假设您在关系数据库中有一个名为my_users的表.最初您有一个名为"full_name"的列,现在您的软件在V2中,您希望删除此列,在空白处拆分全名,并将第一部分放在名为"first_name"的列中,将第二部分放在列中名为last_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不是运行时加载的类的成员,所以你基本上需要在同一个脚本中有两个版本的代码(嗯,自定义类加载器听起来很痛苦),你的类的新版本属于另一个包(听起来很乱),或使用我提到的版本x + 1 x + 2策略(需要更多的计划).也许有一些明显的解决方案我从未从db4o文档中收集过.
有任何想法吗?希望这有一定道理.
Gam*_*lor 10
首先,db4o处理"简单" 场景,例如自动添加或删除字段.添加字段时,所有现有对象都存储了默认值.删除字段时,现有对象的数据仍在数据库中,您仍然可以访问它.重命名字段等是特殊的"重构"调用.
现在你的场景你会做这样的事情:
我们假设我们有一个'地址'类.'full_name'字段已被删除.现在我们不想把它复制到'firstname'和'surname'.然后就可以这样(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);
}
Run Code Online (Sandbox Code Playgroud)
正如您所建议的那样,您可以为每个版本碰撞编写迁移代码.它不再是你班级的一部分,你必须使用上面的'StoredField'-API访问它.
您可以获得所有"存储"类的列表ObjectContainer.ext().storedClasses().有了StoredClass.getStoredFields()你可以获得所有商店字段的列表,没有其他字段在你的班级中不再存在.如果某个类不再存在,您仍然可以通过"GenericObject"类获取对象并访问它.
更新:适用于需要通过多个版本步骤迁移数据库的复杂方案.
例如,在版本v3中,address-object看起来完全不同.所以v1到v2的'migration-script'不再需要它所需的字段(在我的例子中是firstname和surename).我认为处理这个问题有多种可能性.