1

我想将 Person 对象存储在 DB4O 中。人员位置字段可以随时间更改。所以我从数据库中检索一个人并调用一个方法来将位置字段设置为一个新的位置对象。(我希望 Location 对象是不可变的,即 DDD 值对象)。

这可行,但是先前分配的 Location 对象仍保留在数据库中。如何配置 DB4O 以除去这些孤立的 Location 对象?还是我需要一些自定义过程来进行垃圾收集?

此示例的简化类:

class Person {
    Location location;
    public void Move(Location newLocation) { 
        location = newLocation;
    }
}

class Location {
    public Location(string city) { 
        this.City = city;
        //etc
    }
    public readonly string City;
    /// more fields...
}

编辑:更多信息 - Person 是一个 DDD 聚合根。因此,没有对一个人的内部状态的外部引用。如果 Person 更新了它的位置,那么旧的位置应该不复存在。

4

5 回答 5

1

我认为没有完美的解决方案。但是通过一些工作,您几乎可以实现这种行为。这里已经讨论了一个类似的话题。

第一步是在位置字段上激活级联删除。所以当一个人被删除时,位置也会被删除。

configuration.common().objectClass(Person.class).objectField("location").cascadeOnDelete(true);

现在我们需要处理位置变化的情况。这个想法是这样的:

  1. 在激活事件上注册。在那里你“记得”嵌入了哪个对象
  2. 注册更新事件。在那里你检查它是否仍然是同一个嵌入对象。如果没有,你删除旧的。
  3. 非常重要:永远不要“共享”嵌入的对象,否则它将被所有人删除。一个简单的解决方案是在分配位置对象时创建它的副本。

实现此行为的 Java-Demo 。

好吧,这只是概念,距离可接受的解决方案还有很长的路要走:

  1. 利用属性或其他配置来指定哪些对象是这样的
  2. 构建事件处理程序等的健壮实现。
  3. 确保不删除“共享”位置的可靠解决方案
于 2010-03-07T21:35:18.257 回答
0

How about using db4o's delete() first on the old location and then storing the new one?

Best!

German

于 2010-03-04T16:22:54.917 回答
0

你有没有想过把它变成一个值类型?

于 2010-03-04T18:32:45.453 回答
0

这对我来说真的像是一笔交易。

正如 German 所说,您必须删除旧的,存储并分配新的,并确保可以一次性提交这些步骤。

在 RDBMS 中,您也必须为此提出一个事务。然而,许多 RDBMS 系统在这里为您提供触发器和事件支持。请注意,db4o 还提供某些回调。

我目前正在为这种情况进行引用计数抽象,但一般处理起来非常棘手。另一方面,您可以编写一个特定的Update方法来为您简化事务并比较新旧对象的引用。如果它们不匹配并且您可以确定没有其他人引用该类型的地址对象,您可以将其删除。

另请注意,如果您使用的语言没有垃圾收集,您还必须手动跟踪并删除旧对象。

“总根”的概念对我来说似乎很模糊——毕竟,这取决于视角,但这是另一个问题。

于 2010-03-06T10:22:55.690 回答
0

根据cascadeOnDelete(boolean)的 db4o 8.0 API 参考,应该自动删除旧对象。这是文档的副本,请检查给定的示例。

设置级联删除行为。

将 cascadeOnDelete 设置为 true 将导致删除此类实例的所有成员对象,如果它们被传递给 ObjectContainer.delete(Object)。

小心!
此设置还将在调用 ObjectContainer.store(Object) 时触发删除旧成员对象。

行为示例:

对象容器骗局;
酒吧 bar1 = 新酒吧();
酒吧 bar2 = 新酒吧();
foo.bar = bar1;
con.store(foo); // bar1 存储为 foo 的成员
foo.bar = bar2;
con.store(foo); // bar2 存储为 foo 的成员

最后一条语句还将从 ObjectContainer 中删除 bar1,无论有多少其他存储的对象持有对 bar1 的引用。

默认设置为假。

在客户端-服务器环境中,此设置应在客户端和服务器上使用。

此设置可应用于打开的对象容器。

参数:
flag - 是否将删除级联到成员对象。
也可以看看:
ObjectField.cascadeOnDelete(boolean), ObjectContainer.delete(Object), 使用回调

但是它不像打印的那样工作,很奇怪。

于 2012-10-09T07:22:51.570 回答