如何在对象数据库中设计多对多关系?

时间:2022-10-04 10:54:14

I thought it was about time to have a look at OO databases and decided to use db4o for my next little project - a small library.

我认为现在是时候看看OO数据库,并决定将db4o用于我的下一个小项目 - 一个小型库。

Consider the following objects: Book, Category.

请考虑以下对象:Book,Category。

A Book can be in 0-n categories and a Category can be applied to 0-m Books.

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

My first thought is to have a joining object such as BookCatecory but after a bit of Googling I see that this is not appropriate for 'Real OO'.

我的第一个想法是有一个连接对象,如BookCatecory,但经过一些谷歌搜索,我发现这不适合'真正的OO'。

So another approach (recommended by many) is to have a list in both objects: Book.categories and Category.books. One side handles the relationship: Book.addCategory adds Category to Book.categories and Book to Category.books. How to handle commits and rollbacks when 2 objects are been altered within one method call?

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

What are your thoughts? The second approach has obvious advantages but, for me at least, the first 'feels' right (better normed).

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

6 个解决方案

#1


If you use object database you don't need to care how relations are stored in database. You define classes and relationships between them. Please read the reference guided to your database. Examples of relationships:

如果使用对象数据库,则无需关心如何在数据库中存储关系。您可以定义它们之间的类和关系。请阅读引导到您的数据库的参考。关系的例子:

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
}

#2


There are really only two ways I can think of to solve this problem, both of which you've mentioned. Personally, I would go with the first approach (creating a mapping object as an OO entity). This prevents you from keeping redundant information around and having to synchronize; it also means that if the association ends up having fields of its own (the date that the book was assigned to that category, let's say), they can be incorporated easily. We use this approach for a variety of associations in our system.

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

The OO entities would look like:

OO实体看起来像:

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

Here you have to keep the relation object and the two collections in synch; however, the collections are optional in this case. Typically you could get the same information with an ORM query, something like: select b.book from BookCategory b where b.category = MyCategory

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

The alternative is to have a setup like:

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

Book {
 Collection<Category> categories
}

Category {
 Collection<Books> books
}

If your ORM/DB tool automatically maintains the associations, this is fine; otherwise, you are stuck updating both collections. (In Hibernate, one side will have the property: inverse=true on the mapping; this side is not updated, so strictly speaking it doesn't need to be maintained. This seems to me like bad practice, though.)

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

If you typically only access the relation one way (for example, getting all of the books in a category), you could eliminate the collection on other side; then I think you would have to work around the ORM tool and use a native query in order to access the relationship from the other direction.

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

We use Hibernate (a java-based Object Relational Mapping tool) on our project; the Hibernate docs are a good reference for OO/relational design problems, though you may have to spend a little time learning Hibernate to make them useful: http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#collections-ofvalues

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

HTH!

#3


I think you're just a little hung up on the relational db way of thinking. Lists in each object is the right OO thing to do. Commits and rollbacks are no problem, they happen in a transaction that commits everything or rolls back everything.

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

#4


In a pure OO database such as GemStone the objects themselves have collections of references to other objects. When the object is referenced from the application the OODBMS generates a proxy that wraps the object. The schema for this is just the persisted object and its collection of references to the objects it refers to. The OODBMS does not necessarily need a link entity.

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

With an O/R mapping layer (assuming it is clever enough to do M:M relationships) the M:M relationship is manifested as a collection of subsidiary references on the object itself which the O/R mapper resolves to the link entity behind the scenes. Not all O/R mappers do this, so you may have a separate link object.

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

#5


Do you have any particular reason you wanted to use an ODBMS? For simple data structures (such as categorizing books) you generally won't find any advantage in ODBMS over RDBMS, and in fact will have an easier time working in the much-more-standardized world of RDBMS. ODBMS has very tangible advantages when you are working with complex data types or literal persistence/storage of dynamic objects. ODBMS also is cited as being much faster and more scalable than RDBMS, though I can offer little insight into this myself. Here are a couple pages that discuss RDBMS vs. ODBMS, however:

您是否有任何特殊原因要使用ODBMS?对于简单的数据结构(例如书籍分类),您通常不会在ODBMS中找到任何优于RDBMS的优势,事实上将更容易在更加标准化的RDBMS世界中工作。当您处理复杂数据类型或动态对象的文字持久性/存储时,ODBMS具有非常明显的优势。 ODBMS也被认为比RDBMS更快,更具可扩展性,尽管我自己也无法提供这方面的知识。这里有几页讨论RDBMS与ODBMS,但是:

Whatever Happened to Object-Oriented Databases

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

Object-Oriented Database vs. Object-Rleational Database (SO)

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

#6


I would avoid data duplication because then you run into all kinds of problems with merging the differences.

我会避免数据重复,因为你会遇到各种问题,合并差异。

the trick to this is references.

这个技巧就是参考。

the result is that I would have each object contain a collection of references to the other object type as well as having an independent collection of the other objects.

结果是我会让每个对象包含对另一个对象类型的引用的集合,以及具有其他对象的独立集合。

The matching table is a relational concept, unless that intermediary connecting class may have properties that are not attributable to either of the objects. It is there as it enables queries to be written in a powerful manner as it reduces the relation to 2 one to many relations and greatly reduces data duplication. If you did this in a relation database without the matching table then things would get evil very quickly - how would an update operate? Personally i find the attraction of oo databases to be stepping away from this

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

the way that i would tie all the objects together is via events in code to some kind of transaction handler to allow the caching of objects states. so rather than objects manipulating each others properties they request a change through the handler and await the result in a callback.

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

#1


If you use object database you don't need to care how relations are stored in database. You define classes and relationships between them. Please read the reference guided to your database. Examples of relationships:

如果使用对象数据库,则无需关心如何在数据库中存储关系。您可以定义它们之间的类和关系。请阅读引导到您的数据库的参考。关系的例子:

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
}

#2


There are really only two ways I can think of to solve this problem, both of which you've mentioned. Personally, I would go with the first approach (creating a mapping object as an OO entity). This prevents you from keeping redundant information around and having to synchronize; it also means that if the association ends up having fields of its own (the date that the book was assigned to that category, let's say), they can be incorporated easily. We use this approach for a variety of associations in our system.

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

The OO entities would look like:

OO实体看起来像:

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

Here you have to keep the relation object and the two collections in synch; however, the collections are optional in this case. Typically you could get the same information with an ORM query, something like: select b.book from BookCategory b where b.category = MyCategory

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

The alternative is to have a setup like:

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

Book {
 Collection<Category> categories
}

Category {
 Collection<Books> books
}

If your ORM/DB tool automatically maintains the associations, this is fine; otherwise, you are stuck updating both collections. (In Hibernate, one side will have the property: inverse=true on the mapping; this side is not updated, so strictly speaking it doesn't need to be maintained. This seems to me like bad practice, though.)

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

If you typically only access the relation one way (for example, getting all of the books in a category), you could eliminate the collection on other side; then I think you would have to work around the ORM tool and use a native query in order to access the relationship from the other direction.

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

We use Hibernate (a java-based Object Relational Mapping tool) on our project; the Hibernate docs are a good reference for OO/relational design problems, though you may have to spend a little time learning Hibernate to make them useful: http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#collections-ofvalues

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

HTH!

#3


I think you're just a little hung up on the relational db way of thinking. Lists in each object is the right OO thing to do. Commits and rollbacks are no problem, they happen in a transaction that commits everything or rolls back everything.

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

#4


In a pure OO database such as GemStone the objects themselves have collections of references to other objects. When the object is referenced from the application the OODBMS generates a proxy that wraps the object. The schema for this is just the persisted object and its collection of references to the objects it refers to. The OODBMS does not necessarily need a link entity.

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

With an O/R mapping layer (assuming it is clever enough to do M:M relationships) the M:M relationship is manifested as a collection of subsidiary references on the object itself which the O/R mapper resolves to the link entity behind the scenes. Not all O/R mappers do this, so you may have a separate link object.

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

#5


Do you have any particular reason you wanted to use an ODBMS? For simple data structures (such as categorizing books) you generally won't find any advantage in ODBMS over RDBMS, and in fact will have an easier time working in the much-more-standardized world of RDBMS. ODBMS has very tangible advantages when you are working with complex data types or literal persistence/storage of dynamic objects. ODBMS also is cited as being much faster and more scalable than RDBMS, though I can offer little insight into this myself. Here are a couple pages that discuss RDBMS vs. ODBMS, however:

您是否有任何特殊原因要使用ODBMS?对于简单的数据结构(例如书籍分类),您通常不会在ODBMS中找到任何优于RDBMS的优势,事实上将更容易在更加标准化的RDBMS世界中工作。当您处理复杂数据类型或动态对象的文字持久性/存储时,ODBMS具有非常明显的优势。 ODBMS也被认为比RDBMS更快,更具可扩展性,尽管我自己也无法提供这方面的知识。这里有几页讨论RDBMS与ODBMS,但是:

Whatever Happened to Object-Oriented Databases

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

Object-Oriented Database vs. Object-Rleational Database (SO)

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

#6


I would avoid data duplication because then you run into all kinds of problems with merging the differences.

我会避免数据重复,因为你会遇到各种问题,合并差异。

the trick to this is references.

这个技巧就是参考。

the result is that I would have each object contain a collection of references to the other object type as well as having an independent collection of the other objects.

结果是我会让每个对象包含对另一个对象类型的引用的集合,以及具有其他对象的独立集合。

The matching table is a relational concept, unless that intermediary connecting class may have properties that are not attributable to either of the objects. It is there as it enables queries to be written in a powerful manner as it reduces the relation to 2 one to many relations and greatly reduces data duplication. If you did this in a relation database without the matching table then things would get evil very quickly - how would an update operate? Personally i find the attraction of oo databases to be stepping away from this

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

the way that i would tie all the objects together is via events in code to some kind of transaction handler to allow the caching of objects states. so rather than objects manipulating each others properties they request a change through the handler and await the result in a callback.

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