Лучший способ получить дерево объектов, хранящихся в РСУБД - PullRequest
5 голосов
/ 15 июля 2011

Этот вопрос не зависит от программного обеспечения / платформы.Я просто ищу общий код SQL.

Рассмотрим следующие (очень простые, например, таблицы):

Table: Authors
id   | name
1    | Tyson
2    | Gordon
3    | Tony
etc

Table: Books
id   | author   | title
1    | 1        | Tyson's First Book
2    | 2        | Gordon's Book
3    | 1        | Tyson's Second Book
4    | 3        | Tony's Book
etc

Table: Stores
id   | name
1    | Books Overflow
2    | Books Exchange
etc

Table: Stores_Books
id   | store   | book
1    | 1       | 1
2    | 2       | 4
3    | 1       | 3
4    | 2       | 2

Как видите, существует отношение один ко многиммежду Book с и Author с и отношением "многие ко многим" между Book с и Store с.

Вопрос первый: Какой запрос является лучшимчтобы загрузить одного автора и его книги (и где книги продаются) в объектно-ориентированную программу, где каждая строка представляет экземпляр объекта?

Вопрос второй: Что такоелучший запрос на загрузку всего дерева объектов в объектно-ориентированную программу, где каждая строка представляет экземпляр объекта?

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

Isленивая загрузка - лучший способ сделать это, или я должен использовать объединение и анализировать результат при создании дерева объектов (в попытке загрузить данные)? В этой ситуации, какой будет оптимальный выход соединения / цели избазы данных, чтобы сделать синтаксический анализ настолько простым, насколько это возможно?

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

Ответы [ 3 ]

3 голосов
/ 15 июля 2011

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

Следующие вопросы могут относиться как к вашим вопросам 1, так и к 2.

SELECT a.id, a.name, b.id, b.name FROM authors a LEFT JOIN books b ON a.id=b.author

(псевдокод, в вашей программе, которая делает вызов db)

while (%row=fetchrow) {
   if ($row{a.id} != currentauthor.id) {
      currentauthor.id=$row{a.id};
      currentauthor.name=$row{a.name};
      }
    currentbook=new book($row{b.id, b.name});
    push currentauthor.booklist, currentbook;
    }

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

Перед циклическим просмотром книг / авторов, как указано выше, разбейте всю таблицу магазинов на структуру в моей программе, очень похожую на структуру книги / автора выше, но проиндексированную storeid, и затем выполняйте поиск в этой структуре каждый раз, когда я читаю Записать книгу и сохранить ссылку на таблицу магазина

или, если магазинов много,

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

Вот соответствующая статья в Википедии: http://en.wikipedia.org/wiki/Object-relational_impedance_mismatch

Надеюсь, это поможет!

2 голосов
/ 15 июля 2011

В ОО-программе вы не используете SQL, вместо этого вы позволяете сделать это незаметно для вашего механизма постоянства.Для объяснения:

Если у вас есть объектно-ориентированная программа, вам нужна объектная модель, которая естественным образом представляет концепции автора, книги и магазина.Затем у вас возникает проблема «объект / реляционное отображение».Каким-то образом вы хотите получать данные из базы данных, используя SQL, и при этом работать с вашими объектами естественным образом.

В мире Java мы делаем это с помощью Java Persistence API (JPA).Вы на самом деле не пишете SQL, а просто «аннотируете» Java-класс, чтобы сказать «Этот класс соответствует этой таблице, этот атрибут - этому столбцу», а затем делаете некоторые интересные вещи с JOIN и фактически можете выбрать любой Lazy.или Стремитесь к загрузке, поскольку это имеет смысл.

Таким образом, вы можете получить класс Author (для краткости я делаю здесь атрибуты общедоступными, в реальной жизни у нас есть личные атрибуты, методы получения и установки.

 @Entity
 public Class Author {
     public int id; 
     public String name;
     // more in a minute

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

    PUBLISHED_AUTHOR => Author,  
    FULL_NAME => name

А как насчет JOINS и отношений? Класс автора имеет коллекцию Books

   @Entity
   public Class Author {
     public int id; 
     public String name;
     public List<Book> books;

, а класс Book имеет атрибут, которыйэто автор

   @Entity
   public Class Book {
       public int id;
       public String title
       public Author author

Класс JPA Entity Manager извлекает экземплярBook с использованием метода find (я не буду вдаваться в подробности)

   int primaryKey = 1;
   Book aBook = em.find( primaryKey); // approximately

Теперь ваш код может просто идти

   aBook.author.name  

Вы никогда не увидите тот факт, что SQL использовался дляизвлекайте данные для Book, и к тому времени, когда вы запрашиваете атрибут author, также извлекаются данные об авторе.SQL JOIN вполне может быть использован, вам не нужно знать.Вы можете контролировать, будет ли выборка Eager или Lazy с помощью большего количества аннотаций.

Аналогично

    int primaryKey = 2
    Author author = em.find( primaryKey ); 

    author.books.size() ; // how many books did the author write?

мы получаем список всех книг, а также авторов других данных, SQL произошло, мыне видел этого

1 голос
/ 15 июля 2011

Вот несколько примеров T-SQL, с которых можно начать:

1.

выберите a.name, b.title из списка авторов книг b на a.id = b.author

2.

выберите a.name, b.title, s.name из списка Авторы объединения Книги b на a.id = b.author объединение Stores_Books sb на sb.book = b.id присоединиться к магазинам s на s.id = sb.store

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