2010-03-04 39 views
1

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

这有效,但先前分配的位置对象仍然是数据库。我如何配置DB4O以删除这些孤立的位置对象?或者我需要一些自定义流程来垃圾收集?

此示例简化类:

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... 
} 

编辑:一些更多信息 - 人意味着是DDD聚合根。所以没有外部引用一个人的内部状态。如果人员更新其位置,则旧位置应该不存在。

+0

wtf是DDD dawg –

回答

1

我认为没有完美的解决方案可用。但通过一些工作,你几乎可以实现这种行为。类似的主题是already discussed here

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

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

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

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

有Java-Demo其中implements this behavior

好吧,这只是概念,这是一个很长的路到一个可接受的解决方案:

  1. 利用属性或其他配置来指定哪些对象是这样的
  2. 建立一个强大的执行事件处理程序等
  3. 一种固体溶液,以确保一个“共享”的位置并没有被删除
+0

这是一个很好的答案。我一直在调查使用事件来做到这一点。我很高兴我们同意这是一个可行的方法。 –

0

如何在旧位置首先使用db4o的delete(),然后存储新位置?

最好!

德国

+0

我已经使代码示例更能代表我的情况。位置字段是私人的。 我希望持久层自动删除旧的位置对象。否则,我必须开始深入研究每个对象,然后清理干净。 –

0

您是否想过让它成为一种价值型?

+0

我宁愿不必在顶层对象下面的任何地方开始使用结构。 –

+0

是的,那可能是一团糟......他们应该添加将数据库视角作为值类型对待引用对象的能力。 – 2010-03-05 18:00:13

0

这对我来说确实看起来像一个交易。

就像德国人说的,你必须删除旧的,存储并分配新的,并确保这些步骤可以一次完成。

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

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

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

'聚合根'的概念对我来说似乎很模糊 - 毕竟它取决于视角,但这是另一个问题。

+0

我正在调查在激活时遍历来自根对象的对象参考图形,将其存储并更新后,我可以与更新后的对象图形进行比较。任何遗漏的东西都可以删除。 –

+0

这意味着你假设你的位置对象永远不会被别的引用? 我仍然不觉得删除对象应该以某种隐藏的,自动的方式进行,但这似乎是一个主要问题 - 毕竟垃圾收集也是一个很酷的功能。就我个人而言,我还没有准备好保留数据的功能。 – mnemosyn

0

CAS db4o的8.0 API参考cadeOnDelete(布尔值),应该自动删除旧对象。这里是该文档的副本,请查看给出的示例。

 
sets cascaded delete behaviour. 

Setting cascadeOnDelete to true will result in the deletion of all member objects of instances of this class, if they are passed to ObjectContainer.delete(Object). 

Caution ! 
This setting will also trigger deletion of old member objects, on calls to ObjectContainer.store(Object). 

An example of the behaviour: 

ObjectContainer con; 
Bar bar1 = new Bar(); 
Bar bar2 = new Bar(); 
foo.bar = bar1; 
con.store(foo); // bar1 is stored as a member of foo 
foo.bar = bar2; 
con.store(foo); // bar2 is stored as a member of foo 

The last statement will also delete bar1 from the ObjectContainer, no matter how many other stored objects hold references to bar1. 

The default setting is false. 

In client-server environment this setting should be used on both client and server. 

This setting can be applied to an open object container. 

Parameters: 
flag - whether deletes are to be cascaded to member objects. 
See Also: 
ObjectField.cascadeOnDelete(boolean), ObjectContainer.delete(Object), Using callbacks 

然而,它不能像印刷,奇怪的工作。