Как создать отношения "многие ко многим" в базе данных объектов?
Я подумал, что пришло время взглянуть на базы данных 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
Я бы избегал дублирования данных, потому что тогда вы сталкиваетесь со всеми проблемами при слиянии различий.
трюк к этому - ссылки.
результат состоит в том, что каждый объект должен содержать набор ссылок на другой тип объекта, а также иметь независимый набор других объектов.
Таблица соответствия является реляционной концепцией, если только этот промежуточный класс соединения не может иметь свойств, которые не относятся ни к одному из объектов. Он существует, поскольку он позволяет писать запросы мощным образом, поскольку он уменьшает отношение к отношениям от одного до нескольких и значительно уменьшает дублирование данных. Если вы сделали это в базе данных отношений без соответствующей таблицы, тогда все получило бы зло очень быстро - как будет работать обновление? Лично я нахожу привлекательность баз данных оо, чтобы отступить от этого
способ связать все объекты вместе с событиями в коде каким-то обработчиком транзакций, чтобы обеспечить кеширование состояний объектов. поэтому вместо объектов, управляющих свойствами друг друга, они запрашивают изменение через обработчик и ждут результата в обратном вызове.