15

我认为是时候看看 OO 数据库了,并决定在我的下一个小项目——一个小型库中使用 db4o。

考虑以下对象:书籍、类别。

一本书可以在 0-n 个类别中,一个类别可以应用于 0-m 本书。

我的第一个想法是拥有一个诸如 BookCatecory 之类的连接对象,但经过一番谷歌搜索后,我发现这不适合“真正的 OO”。

因此,另一种方法(许多人推荐)是在两个对象中都有一个列表:Book.categories 和 Category.books。一方面处理关系:Book.addCategory 将 Category 添加到 Book.categories 并将 Book 添加到 Category.books。在一个方法调用中更改 2 个对象时如何处理提交和回滚?

你怎么认为?第二种方法具有明显的优势,但至少对我来说,第一种“感觉”是正确的(更好的规范)。

4

6 回答 6

9

我真的只有两种方法可以解决这个问题,这两种方法你都提到了。就个人而言,我会采用第一种方法(将映射对象创建为 OO 实体)。这可以防止您保留冗余信息并且必须同步;这也意味着,如果协会最终拥有自己的字段(比如说,书籍被分配到该类别的日期),它们可以很容易地合并。我们将这种方法用于我们系统中的各种关联。

OO 实体如下所示:

BookCategory {
 Book book
 Category category
}
Book {
 Collection <BookCategory> categories
}
Category {
 Collection <BookCategory> categories
}

在这里,您必须保持关系对象和两个集合同步;但是,在这种情况下,集合是可选的。通常,您可以使用 ORM 查询获得相同的信息,例如: select b.book from BookCategory b where b.category = MyCategory

另一种方法是进行如下设置:

Book {
 Collection<Category> categories
}

Category {
 Collection<Books> books
}

如果您的 ORM/DB 工具自动维护关联,这很好;否则,您将无法更新这两个集合。(在 Hibernate 中,一侧将在映射上具有属性:inverse=true;这一侧未更新,因此严格来说不需要维护。不过,在我看来,这似乎是一种不好的做法。)

如果您通常仅以一种方式访问​​关系(例如,获取一个类别中的所有书籍),则可以消除另一侧的集合;那么我认为您必须使用 ORM 工具并使用本机查询才能从另一个方向访问关系。

我们在项目中使用 Hibernate(一个基于 java 的对象关系映射工具);Hibernate 文档是 OO/关系设计问题的一个很好的参考,尽管您可能需要花一点时间学习 Hibernate 以使其有用: http ://docs.jboss.org/hibernate/stable/core/reference/en/ html_single/#collections-ofvalues

于 2009-09-02T19:40:17.560 回答
4

如果您使用对象数据库,则无需关心关系是如何存储在数据库中的。您定义类和它们之间的关系。请阅读您的数据库的参考指南。关系示例:

n:n attribute, referencing from the parent
------------------------------------------------------------------
class Person {
    List addresses;
}

class Address {
}


n:n attribute, referencing from the child
------------------------------------------------------------------
class Person {
}

class Address {
    List persons
}

n:n attribute, bidirectional references
------------------------------------------------------------------
class Person {
    List addresses;
}

class Address {
    List persons
}
于 2009-07-01T13:52:24.603 回答
1

我认为您只是有点沉迷于关系数据库的思维方式。每个对象中的列表是正确的 OO 事情。提交和回滚没有问题,它们发生在提交所有内容或回滚所有内容的事务中。

于 2009-07-01T13:50:01.113 回答
1

在诸如 GemStone 之类的纯 OO 数据库中,对象本身具有对其他对象的引用集合。当从应用程序引用对象时,OODBMS 会生成一个包装该对象的代理。这个模式只是持久化的对象和它引用的对象的引用集合。OODBMS 不一定需要链接实体。

使用 O/R 映射层(假设它足够聪明地进行 M:M 关系),M:M 关系表现为对象本身的附属引用的集合,O/R 映射器将其解析为对象后面的链接实体场景。并非所有的 O/R 映射器都这样做,因此您可能有一个单独的链接对象。

于 2009-07-01T13:51:19.923 回答
1

您有什么特别的原因想要使用 ODBMS?对于简单的数据结构(例如对书籍进行分类),您通常不会发现 ODBMS 比 RDBMS 有任何优势,事实上,在更加标准化的 RDBMS 世界中工作会更容易。当您处理复杂的数据类型或动态对象的字面持久性/存储时,ODBMS 具有非常明显的优势。ODBMS 也被认为比 RDBMS 更快且更具可扩展性,尽管我自己对此几乎无法提供洞察力。然而,这里有几页讨论 RDBMS 与 ODBMS:

面向对象的数据库发生了什么

面向对象的数据库与对象关系数据库 (SO)

于 2009-07-01T13:54:31.617 回答
0

我会避免数据重复,因为这样您在合并差异时会遇到各种问题。

诀窍是参考。

结果是我会让每个对象都包含对其他对象类型的引用的集合,并拥有其他对象的独立集合。

匹配表是一个关系概念,除非该中间连接类可能具有不属于任何一个对象的属性。它在那里是因为它使查询能够以强大的方式编写,因为它将关系减少到 2 个一对多关系并大大减少了数据重复。如果您在没有匹配表的关系数据库中执行此操作,那么事情会很快变得糟糕 - 更新将如何操作?就我个人而言,我发现 oo 数据库的吸引力正在远离这一点

我将所有对象绑定在一起的方式是通过代码中的事件到某种事务处理程序,以允许缓存对象状态。因此,它们不是通过处理程序请求更改并在回调中等待结果,而不是对象操纵彼此的属性。

于 2009-07-01T14:04:58.307 回答