Как создать отношения "многие ко многим" в базе данных объектов?

Я подумал, что пришло время взглянуть на базы данных OO и решил использовать db4o для моего следующего небольшого проекта - небольшой библиотеки.

Рассмотрим следующие объекты: Книга, Категория.

Книга может быть в 0-n категориях, а Категория может быть применена к 0-м книгам.

Моя первая мысль состоит в том, чтобы иметь объект объединения, такой как BookCatecory, но после небольшого Googling я вижу, что это не подходит для "Real OO".

Таким образом, другой подход (рекомендуется многими) заключается в том, чтобы иметь список в обоих объектах: Book.categories и Category.books. Одна сторона обрабатывает отношения: Book.addCategory добавляет категорию в Book.categories и книги в Category.books. Как обрабатывать фиксации и откаты, когда в одном вызове метода было изменено 2 объекта?

Каковы ваши мысли? Второй подход имеет очевидные преимущества, но для меня, по крайней мере, первое "чувствует" право (лучше нормировано).

Ответы

Ответ 1

Если вы используете объектную базу данных, вам не нужно заботиться о том, как отношения хранятся в базе данных. Вы определяете классы и отношения между ними. Пожалуйста, прочитайте ссылку на вашу базу данных. Примеры отношений:

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

На самом деле есть только два способа решить эту проблему, обоим из которых вы уже упоминали. Лично я бы пошел с первым подходом (созданием объекта сопоставления как объекта OO). Это не позволяет вам сохранять избыточную информацию и синхронизировать ее; это также означает, что если ассоциация заканчивается наличием собственных полей (например, дата, когда книга была присвоена этой категории, скажем), их можно легко включить. Мы используем этот подход для различных ассоциаций в нашей системе.

Объекты OO будут выглядеть так:

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

Здесь вы должны синхронизировать объект отношения и две коллекции; однако коллекции в этом случае не являются обязательными. Как правило, вы можете получить ту же информацию с запросом ORM, что-то вроде: выберите b.book из BookCategory b, где b.category = MyCategory

Альтернативой является установка, например:

Book {
 Collection<Category> categories
}

Category {
 Collection<Books> books
}

Если ваш инструмент ORM/DB автоматически поддерживает ассоциации, это нормально; в противном случае вы застряли в обновлении обеих коллекций. (В Hibernate одна сторона будет иметь свойство: inverse = true на отображении, эта сторона не обновляется, поэтому, строго говоря, ее не нужно поддерживать. Однако это кажется мне плохой практикой.)

Если вы обычно получаете доступ только к одному из способов (например, получить все книги в категории), вы можете удалить коллекцию с другой стороны; то я думаю, вам придется работать с инструментом ORM и использовать собственный запрос, чтобы получить доступ к отношениям с другого направления.

В нашем проекте мы используем Hibernate (java-based Object Relational Mapping tool); документы Hibernate являются хорошей ссылкой для проблем с OO/реляционным дизайном, хотя вам, возможно, придется потратить немного времени на изучение Hibernate, чтобы сделать их полезными: http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#collections-ofvalues

НТН!

Ответ 3

Я думаю, вы просто немного зависели от реляционного db способа мышления. Списки в каждом объекте - это правильная вещь OO. Обязательства и откаты не являются проблемой, они происходят в транзакции, которая совершает все или откатывает все.

Ответ 4

В чистой базе данных OO, такой как GemStone, сами объекты имеют коллекции ссылок на другие объекты. Когда объект ссылается на приложение, OODBMS создает прокси-сервер, который обертывает объект. Схема для этого - это только сохраняемый объект и его коллекция ссылок на объекты, на которые он ссылается. OODBMS необязательно нуждается в объекте связи.

С слоем отображения O/R (предполагая, что он достаточно умен для выполнения отношений M: M), отношение M: M проявляется как совокупность вспомогательных ссылок на самом объекте, который ретранслятор O/R разделяет на ссылку за кулисами. Не все маркеры O/R делают это, поэтому у вас может быть отдельный объект ссылки.

Ответ 5

Есть ли у вас какая-то особая причина, по которой вы хотели использовать ODBMS? Для простых структур данных (таких как категоризация книг) вы, как правило, не найдете каких-либо преимуществ в ODBMS над РСУБД, и на самом деле будет легче работать в гораздо более стандартизованном мире РСУБД. ODBMS имеет очень осязаемые преимущества, когда вы работаете со сложными типами данных или буквально сохраняете/сохраняете динамические объекты. ODBMS также цитируется как гораздо более быстрый и масштабируемый, чем RDBMS, хотя я могу немного рассказать об этом сам. Вот пара страниц, где обсуждаются RDBMS и ODBMS:

Что бы ни случилось с объектно-ориентированными базами данных

Объектно-ориентированная база данных и объектно-реляционная база данных (SO)

Ответ 6

Я бы избегал дублирования данных, потому что тогда вы сталкиваетесь со всеми проблемами при слиянии различий.

трюк к этому - ссылки.

результат состоит в том, что каждый объект должен содержать набор ссылок на другой тип объекта, а также иметь независимый набор других объектов.

Таблица соответствия является реляционной концепцией, если только этот промежуточный класс соединения не может иметь свойств, которые не относятся ни к одному из объектов. Он существует, поскольку он позволяет писать запросы мощным образом, поскольку он уменьшает отношение к отношениям от одного до нескольких и значительно уменьшает дублирование данных. Если вы сделали это в базе данных отношений без соответствующей таблицы, тогда все получило бы зло очень быстро - как будет работать обновление? Лично я нахожу привлекательность баз данных оо, чтобы отступить от этого

способ связать все объекты вместе с событиями в коде каким-то обработчиком транзакций, чтобы обеспечить кеширование состояний объектов. поэтому вместо объектов, управляющих свойствами друг друга, они запрашивают изменение через обработчик и ждут результата в обратном вызове.