2009-07-01 15 views
14

Pensavo che fosse giunto il momento di dare un'occhiata ai database OO e ho deciso di utilizzare db4o per il mio prossimo piccolo progetto: una piccola libreria.Come progettare relazioni molti-a-molti in un database di oggetti?

Considerare i seguenti oggetti: Libro, Categoria.

Un libro può essere in categorie 0-n e una categoria può essere applicata ai libri da 0-m.

Il mio primo pensiero è di avere un oggetto di congiunzione come BookCatecory ma dopo un po 'di ricerca su Google vedo che questo non è appropriato per "Real OO".

Quindi un altro approccio (consigliato da molti) è quello di avere una lista in entrambi gli oggetti: Book.categories e Category.books. Un lato gestisce la relazione: Book.addCategory aggiunge Categoria a Book.categories e Book to Category.books. Come gestire commit e rollback quando 2 oggetti sono stati modificati all'interno di una chiamata di metodo?

Quali sono i tuoi pensieri? Il secondo approccio ha evidenti vantaggi ma, almeno per me, il primo 'sente' giusto (meglio normato).

risposta

5

Se si utilizza il database degli oggetti, non è necessario preoccuparsi di come le relazioni vengono archiviate nel database. Definisci classi e relazioni tra loro. Si prega di leggere il riferimento guidato al proprio database. Esempi di relazioni:

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 
} 
1

Penso che tu sia solo un po 'appeso al modo di pensare relazionale. Le liste in ogni oggetto sono la giusta cosa OO da fare. I commit e i rollback non sono un problema, si verificano in una transazione che impegna tutto o ripristina tutto.

1

In un database OO puro come GemStone gli oggetti stessi hanno raccolte di riferimenti ad altri oggetti. Quando l'oggetto viene referenziato dall'applicazione, l'OODBMS genera un proxy che avvolge l'oggetto. Lo schema per questo è solo l'oggetto persistente e la sua collezione di riferimenti agli oggetti a cui fa riferimento. L'OODBMS non ha necessariamente bisogno di un'entità di collegamento.

Con uno strato di mappatura O/R (supponendo che sia abbastanza intelligente da eseguire relazioni M: M) la relazione M: M si manifesta come una raccolta di riferimenti sussidiari sull'oggetto stesso che il mappatore O/R risolve in collegare l'entità dietro le quinte. Non tutti i mappatori O/R eseguono questa operazione, quindi potresti avere un oggetto di collegamento separato.

1

Avete qualche motivo particolare per cui desiderate utilizzare un ODBMS? Per strutture dati semplici (come la categorizzazione di libri) in genere non troverete alcun vantaggio in ODBMS su RDBMS, e in effetti sarà più facile lavorare nel mondo molto più standardizzato di RDBMS. ODBMS ha vantaggi molto tangibili quando si lavora con tipi di dati complessi o persistenza/memorizzazione letterale di oggetti dinamici. ODBMS viene anche indicato come molto più veloce e più scalabile rispetto a RDBMS, sebbene io possa offrire a me stesso una visione poco approfondita. Qui ci sono un paio di pagine che discutono RDBMS contro ODBMS, però:

Whatever Happened to Object-Oriented Databases

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

+0

Volevo vedere se potevo evitare di creare un dbschema, creare tabelle, creare oggetti, mappare tabelle ad oggetti, ecc ecc. Ecc. Sembra che un odbms potrebbe tagliare molto del lavoro dell'asino ... – paul

+0

Potrebbe tagliare un po 'di quel lavoro, ma anche un buon livello di ORM. Non sto dicendo che ODBMS sia la scelta sbagliata, ma ci sono alternative che potrebbero servire anche a te o meglio. –

0

vorrei evitare la duplicazione dei dati, perché poi si esegue in tutti i tipi di problemi con la fusione delle differenze.

il trucco per questo è riferimenti.

il risultato è che avrei ogni oggetto contenere una raccolta di riferimenti all'altro tipo di oggetto oltre ad avere una collezione indipendente degli altri oggetti.

La tabella di corrispondenza è un concetto relazionale, a meno che tale classe di collegamento intermediaria possa avere proprietà non attribuibili a nessuno degli oggetti. È lì in quanto consente alle query di essere scritte in modo potente in quanto riduce la relazione a 2 da una a molte relazioni e riduce notevolmente la duplicazione dei dati. Se lo facessi in un database di relazioni senza la tabella di corrispondenza, le cose si farebbero molto presto male - come funzionerebbe un aggiornamento? Personalmente trovo che l'attrazione dei database oo passi da questo

il modo in cui legheremo tutti gli oggetti è tramite eventi in codice a un qualche tipo di gestore di transazioni per consentire la memorizzazione nella cache degli stati degli oggetti. così, piuttosto che gli oggetti che manipolano le proprietà degli altri, richiedono un cambiamento attraverso il gestore e attendono il risultato in una richiamata.

8

Ci sono davvero solo due modi in cui posso pensare di risolvere questo problema, entrambi i quali hai menzionato. Personalmente, andrei con il primo approccio (creando un oggetto di mappatura come entità OO). Ciò ti impedisce di mantenere le informazioni ridondanti e di sincronizzarle; significa anche che se l'associazione finisce per avere campi propri (la data in cui il libro è stato assegnato a quella categoria, diciamo), possono essere incorporati facilmente. Usiamo questo approccio per una varietà di associazioni nel nostro sistema.

Le entità OO sarebbe simile:

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

Qui devi tenere l'oggetto relazione e le due collezioni in sintonia; tuttavia, le raccolte sono facoltative in questo caso. In genere si potrebbe ottenere le stesse informazioni con una query ORM, qualcosa di simile: selezionare b.book da BookCategory b dove b.category = MyCategory

L'alternativa è quella di avere una configurazione simile:

Book { 
Collection<Category> categories 
} 

Category { 
Collection<Books> books 
} 

Se il tuo strumento ORM/DB mantiene automaticamente le associazioni, questo va bene; altrimenti, sei bloccato ad aggiornare entrambe le raccolte. (In Hibernate, una parte avrà la proprietà: inverse = true sulla mappatura, questo lato non viene aggiornato, quindi non è necessario mantenerlo rigorosamente.Per questo mi sembra una cattiva pratica, però.)

Se in genere si accede alla relazione solo in un modo (ad esempio, ottenendo tutti i libri in una categoria), è possibile eliminare la raccolta dall'altra parte; quindi penso che dovresti lavorare attorno allo strumento ORM e usare una query nativa per accedere alla relazione dall'altra direzione.

Usiamo Hibernate (uno strumento di mappatura relazionale di oggetti basato su java) sul nostro progetto; i documenti Hibernate sono un buon riferimento per problemi di progettazione relazionale OO, anche se potresti dover dedicare un po 'di tempo all'apprendimento di Hibernate per renderli utili: http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#collections-ofvalues

HTH!

+0

Devo dire che non ho familiarità con db40; questa risposta si applica in generale al problema ORM che stai descrivendo, spero =) – RMorrisey

+0

+1 grazie per la risposta e i suggerimenti per l'ibernazione – paul

Problemi correlati