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

StackOverflow https://stackoverflow.com/questions/1069187

Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

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

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
}

Другие советы

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

Объекты OO будут выглядеть следующим образом:

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

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

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

Book {
 Collection<Category> categories
}

Category {
 Collection<Books> books
}

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

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

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

ХТХ!

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

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

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

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

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

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

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

хитрость в этом заключается в ссылках.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top