M2 ORM2 : Un modello per la gestione trasparente della persistenza relazionale di oggetti Luca Cabibbo e Roberto Porcelli Dipartimento di Informatica e Automazione Università degli studi Roma Tre Sommario Lo sviluppo di applicazioni orientate agli oggetti richiede comunemente di memorizzare degli oggetti in una base di dati. I sistemi per la gestione trasparente della persistenza degli oggetti liberano il programmatore dalle problematiche della gestione della persistenza. Questo lavoro presenta M2 ORM2 , un modello per descrivere corrispondenze basate sull’incontro a metà strada di schemi a oggetti e schemi relazionali, di supporto alla gestione trasparente della persistenza di oggetti mediante basi di dati relazionali. 1 Introduzione Nello sviluppo di sistemi informatici si sono affermate numerose tecnologie, che vanno utilizzate in modo combinato e, possibilmente, sinergico. Da una parte, i sistemi di gestione di basi di dati relazionali consentono una gestione efficiente ed efficace di dati persistenti, condivisi e transazionali [2]. Dall’altra, gli strumenti e i metodi orientati agli oggetti (linguaggi di programmazione, ma anche metodologie di analisi e progettazione) consentono una sviluppo efficace della logica applicativa delle applicazioni [15]. In pratica, è comune realizzare applicazioni a oggetti con una architettura a strati, con almeno uno strato per la logica applicativa, uno di presentazione e uno per la persistenza. Le classi i cui oggetti posseggono i dati che devono essere resi persistenti appartengono allo strato della logica applicativa, e sono normalmente ispirate a classi concettuali della realtà di interesse dell’applicazione. Queste classi, chiamate classi persistenti, vengono rese persistenti scrivendo del codice che le collega in modo opportuno allo strato che si occupa della persistenza dei dati. La persistenza degli oggetti può essere realizzata in vari modi, ad esempio usando una base di dati a oggetti o relazionale. Nel primo caso, ciascun oggetto viene rappresentato direttamente da un oggetto della base di dati a oggetti. Nel secondo caso, i dati di ciascun oggetto vanno rappresentati mediante una o più tuple della base di dati relazione. A livello del codice, la persistenza relazionale degli oggetti può essere poi realizzata in vari modi, ad esempio mediante il linguaggio SQL e le API di JDBC. Nel seguito ci occuperemo di oggetti persistenti gestiti mediante basi di dati relazionali. Recentemente sono stati realizzati dei framework per la gestione trasparente della persistenza degli oggetti [17,20]. Con essi, il programmatore gestisce gli oggetti persistenti usando delle API standard come quelle di ODMG [6], ovvero nello stesso modo in cui userebbe gli oggetti di una base di dati a oggetti. In realtà, questi framework possono rendere persistenti gli oggetti anche mediante una base di dati relazionale oppure dei file. La persistenza è quindi trasparente al programmatore, nel senso che non ne conosce i dettagli effettivi della gestione. La corrispondenza tra gli oggetti e il supporto alla persistenza viene gestita da uno strato software, implementato come un pre-compilatore, un post-compilatore oppure un interprete. La persistenza trasparente degli oggetti può essere ottenuta in vari modi. Nell’R/O mapping (Relation to Object mapping, chiamato anche reverse engineering) vengono generate automaticamente le classi persistenti a partire da una base di dati relazionale. In questo modo, il programmatore popola la base di dati creando o modificando oggetti delle classi persistenti; queste sono realizzate in modo tale da propagare tali creazioni e modifiche nella base di dati sottostante. Nell’O/R mapping (Object to Relation mapping, chiamato anche forward engineering), a partire dalle classi che devono essere rese persistenti viene invece generata automaticamente la base di dati, insieme a tutto il codice necessario a propagare la persistenza degli oggetti nella base di dati. Una gestione della persistenza completamente trasparente non è sempre utile o possibile. Spesso infatti bisogna realizzare applicazioni che accedono a basi di dati relazionali pre-esistenti e condivise tra più applicazioni; questo evidentemente limita l’uso dell’O/R mapping. Inoltre, il progettista della logica applicativa vuole poter sfruttare tutte le potenzialità del modello a oggetti, senza essere vincolato dallo schema della base di dati; questo limita invece l’uso dell’R/O mapping. Fortunatamente, esiste una ulteriore modalità per ottenere la persistenza degli oggetti, che consente di gestire i casi in cui l’applicazione e la base di dati siano state progettate ed evolvono in modo indipendente. Nell’approccio meet in the middle le classi persistenti e la base di dati vengono progettate e realizzate separatamente. Inoltre vengono descritte, solitamente in modo dichiarativo, le corrispondenze che esistono tra le classi persistenti e le relazioni della base di dati. Queste corrispondenze descrivono un “incontro tra schemi a metà strada” e vengono usate dal gestore della persistenza per rendere persistenti gli oggetti mediante la base di dati. L’approccio meet in the middle è molto versatile, perché cambiamenti nelle classi persistenti e/o nella base di dati possono essere gestiti semplicemente ridefinendo le corrispondenze tra i due schemi. Purtroppo, i sistemi esistenti supportano l’approccio meet in the middle solo in casi molto limitati. Molti sistemi per la gestione della persistenza di oggetti sono infatti basati principalmente sull’approccio O/R oppure su quello R/O, e consentono di gestire essenzialmente solo corrispondenze tra strutture simili (ad esempio, gli oggetti di una singola classe con le tuple di una singola relazione); questi sistemi consentono un eventuale incontro tra schemi, ma solo come attività di ottimizzazione locale successiva alla traduzione di uno schema da un modello di dati all’altro. Le limitazioni dei sistemi esistenti sono legate alle difficoltà nel ragionare su corrispondenze complesse per evitare anomalie e inconsistenze. Questo lavoro presenta M2 ORM2 (un acronimo per Meet-in-the-Middle Object/Relational Mapping Model ), un modello per descrivere corrispondenze tra schemi a oggetti e schemi relazionali al fine di supportare la gestione trasparente della persistenza degli oggetti di tipo meet in the middle. Rispetto ai sistemi attualmente esistenti, M2 ORM2 consente maggiori possibilità di incontro tra schemi. Anziché considerare solo corrispondenze tra singole classi e singole relazioni, in M2 ORM2 è anche possibile esprimere corrispondenze tra cluster di classi correlate (che intuitivamente descrivono un singolo concetto) e cluster di relazioni correlate. È inoltre possibile esprimere corrispondenze che descrivono relationship1 tra cluster. Rispetto ad altre proposte, M2 ORM2 fa riferimento a dettagli specifici dei modelli dei dati considerati (a oggetti e relazionale), proprio al fine di identificare maggiori possibilità di incontro tra schemi. Il contributo principale di questo lavoro consiste nella presentazione del modello M2 ORM2 . Inoltre, viene avviata una discussione sulla correttezza delle corrispondenze e vengono identificate alcune condizioni per la correttezza. La Sezione 2 riporta la terminologia e le notazioni usate per descrivere gli schemi a oggetti e gli schemi relazionali. La Sezione 3 introduce il modello M2 ORM2 per descrivere la corrispondenza tra schemi, insieme a degli esempi. La Sezione 4 discute il problema della correttezza delle corrispondenze. Infine, la Sezione 5 discute l’efficacia del modello, confrontandolo con altre proposte. 2 Modello a oggetti e modello relazionale Questa sezione ha lo scopo di illustrare i modelli di dati utilizzati (modello a oggetti e modello relazionale) e le loro caratteristiche (costrutti e vincoli), nonché la terminologia usata. Il modello a oggetti di riferimento è un modello semantico (ovvero, ha caratteristiche strutturali ma non comportamentali) non nidificato e senza gerarchie di generalizzazione/specializzazione. Si tratta di una versione semplificata del modello di ODMG [6] e di quello di UML [4]. A livello intensionale, una classe descrive un insieme di oggetti che hanno le stesse caratteristiche strutturali. Ciascuna classe è caratterizzata da un insieme di attributi, ciascuno con un nome e un tipo.2 Una associazione descrive una relazione binaria tra una coppia di classi (o meglio, tra gli oggetti di tali classi). Uno schema a oggetti è un insieme di classi e associazioni tra tali classi. La Figura 1 mostra un esempio di schema a oggetti. A livello estensionale, una classe è un insieme di oggetti (ogni oggetto è una istanza di una classe). Ciascun oggetto è dotato di un oid, un identificatore univoco che permette di referenziarlo. Lo stato di un oggetto è definito dall’insieme 1 2 Nel seguito, useremo il termine relationship per indicare le relazioni tra elementi, al fine di evitare di usare in modo sovraccarico il termine “relazione”. In questo lavoro viene fatta l’ipotesi semplificativa che gli attributi delle classi siano tutti di uno stesso tipo semplice, ad esempio, delle stringhe. 1 Risiede residenza Comune {RO} -nome {KEY} -provincia * Progetto -nome -budget * Partecipa * progetti Impiegato -matricola {KEY} -cognome -stipendio {null} impiegati Afferisce * dipartimento 1 Dipartimento -nome -divisione Figura 1. Uno schema a oggetti dei valori assunti in un certo momento dagli attributi dell’oggetto. Una associazione è un insieme di collegamenti ; ogni collegamento è una istanza di una associazione e descrive una relazione tra una coppia di oggetti. In questo lavoro vengono considerati anche alcuni vincoli di integrità. Gli attributi di una classe possono assumere oppure non assumere valore nullo; un attributo che non può assumere valore nullo è detto non nullo. Talvolta è utile poter cercare in modo univoco gli oggetti di una classe sulla base del valore assunto da alcuni dei loro attributi; in questo caso, gli attributi che identificano gli oggetti sono chiamati attributi chiave e la classe viene detta con chiave; altrimenti, la classe viene detta senza chiave. Gli attributi chiave devono essere non nulli. Una classe di sola lettura è una classe da cui non è possibile istanziare nuovi oggetti persistenti e non è possibile modificare o cancellare oggetti esistenti. In una applicazione, le classi di sola lettura sono utili per accedere informazioni generate da altre applicazioni ma che non possono essere modificate da questa applicazione. Nella Figura 1, gli attributi chiave sono indicati dal vincolo {KEY}, e gli attributi che possono avere valore nullo sono indicati dal vincolo {null}. Il vincolo {RO} indica le classi di sola lettura. Per le associazioni possono sussistere vincoli di molteplicità e di navigabilità. Un ruolo è una estremità di una associazione, relativo a una classe che partecipa nell’associazione. I ruoli sono caratterizzati da nome, navigabilità e molteplicità. La molteplicità di un ruolo di una associazione indica quanti oggetti (al minimo e al massimo) di quella classe possono essere collegati a ogni oggetto della classe sull’altro ruolo dell’associazione. La navigabilità di un ruolo di una associazione indica se è possibile raggiungere gli oggetti di quella classe navigando i collegamenti dagli oggetti dell’altro ruolo dell’associazione. Ad esempio, nello schema di Figura 1, ciascun Impiegato è associato all’(unico) Comune in cui vive; questa associazione è navigabile dall’Impiegato verso il Comune, ma non viceversa. Nel modello relazionale [2], a livello intensionale una relazione descrive un insieme di tuple. Lo schema di una relazione è costituito da un insieme di attributi, ciascuno con un nome e un tipo.3 Uno schema relazionale è un insieme di 3 Anche in questo caso viene fatta l’ipotesi semplificativa che tutti gli attributi siano di uno stesso tipo semplice, ad esempio, delle stringhe. impiegato partecipazione imp {NK}{FK: impiegato} prog {NK}{FK: progetto} matricola {NK} cognome stipendio {null} comune provincia dip {FK: dipartimento} dipartimento codice {AK} nome div {FK:divisione} progetto codice {AK} denominazione budget dataInizio {null} divisione codice {AK} nome comune {null} Figura 2. Uno schema relazionale relazioni. A livello estensionale, una relazione è un insieme di tuple sugli attributi della relazione. Questo lavoro tiene in considerazione i seguenti vincoli di integrità. Ciascun attributo può essere o non essere non nullo. Ciascuna relazione ha una chiave, ovvero un insieme di uno o più attributi che permette di identificare le tuple della relazione. Un attributo chiave un attributo che fa parte di una chiave; gli attributi chiave devono essere non nulli. Talvolta le relazioni, anziché essere identificate mediante chiavi naturali (ovvero, chiavi basate su attributi che hanno significato nella realtà), vengono identificate mediante chiavi artificiali (o surrogati ). In una relazione con chiave artificiale, l’inserimento di una nuova tupla nella relazione richiede anche la generazione di una nuova chiave artificiale, il che viene normalmente gestito dal DBMS. Per integrità referenziale si intende un insieme di uno o più attributi di una relazione che consente di referenziare le tuple di un’altra relazione. La Figura 2 mostra un esempio di schema relazionale. Gli attributi che formano una chiave naturale sono indicati dal vincolo {NK}, e quelli che formano una chiave artificiale dal vincolo {AK}. Le integratità referenziali sono indicate da frecce e implementate da attributi con il vincolo {FK}. Il vincolo {null} indica gli attributi che possono assumere valore nullo. 3 Un modello per la corrispondenza tra schemi M2 ORM2 (Meet-in-the-Middle Object/Relational Mapping Model ) è un modello per descrivere corrispondenze tra schemi a oggetti e schemi relazionali di supporto alla gestione trasparente della persistenza degli oggetti di tipo meet in the middle. In questo lavoro viene fatta l’ipotesi che lo schema a oggetti e lo schema relazionale siano stati progettati autonomamente. In particolare, lo schema relazionale potrebbe essere (parzialmente) denormalizzato per motivi di efficienza; anche lo schema a oggetti potrebbe essere denormalizzato, fornendo oggetti “a grana grossa”. Oggetti e collegamenti dello schema a oggetti devono poter essere manipolati mediante le cosiddette operazioni CRUD (Create, Read, Update, Delete), consentendo la creazione persistente di oggetti, la lettura di oggetti persistenti (ovvero, la ricerca univoca di oggetti sulla base della chiave), la modifica persistente di oggetti, la cancellazione persistente di oggetti, nonché la navigazione, la formazione, la rottura e la modifica di collegamenti persistenti tra oggetti. 4 Tutte queste operazioni devono essere automaticamente implementate mediante manipolazioni della base di dati relazionale. Una corrispondenza M2 ORM2 è descritta da un multi-grafo orientato, ovvero da un insieme di nodi e da un insieme di archi, con l’osservazione che potrebbero esserci più archi che collegano una stessa coppia di nodi. Ciascun nodo descrive corrispondenze tra un insieme di classi e un insieme di relazioni. Ciascun arco descrive una relationship tra le corrispondenze descritte da una coppia di nodi. Intuitivamente, usando la terminologia del modello Entità-Relazione, ciascun nodo rappresenta una entità (eventualmente non normalizzata in uno dei due schemi) e ciascun arco una relazione (relationship) binaria tra entità. Un cluster di classi (o c-cluster ) è formato da un insieme non vuoto di classi, nonché da un insieme di associazioni tra tali classi.5 In un c-cluster, una delle classi va designata come classe primaria del c-cluster; le altre classi sono secondarie. Le associazioni del nodo devono essere, direttamente o indirettamente, tutte di tipo uno-a-uno oppure uno-a-molti dalla classe primaria alle classi secondarie. Intuitivamente, queste associazioni devono collegare ciascun oggetto della classe primaria ad al più un oggetto di ciascuna delle classi secondarie. Un cluster di relazioni (o r-cluster ) è formato da un insieme non vuoto di relazioni, nonché da eventuali vincoli di integrità tra di esse. In un r-cluster, una delle relazioni va designata come relazione primaria dell’r-cluster; le altre relazioni, dette secondarie, devono essere referenziate, direttamente o indirettamente, dalla relazione primaria dell’r-cluster. Intuitivamente, a ciascun tupla della relazione primaria deve essere associata al più una tupla in ciascuna delle relazioni secondarie mediante le integrità referenziali considerate. Ciascun nodo di una corrispondenza è formato da un c-cluster e da un rcluster, nonché da informazioni sulle corrispondenze tra i loro elementi (ovvero, classi, relazioni, attributi e associazioni). M2 ORM2 prevede tre tipologie di nodi, per fare corrispondere una classe con una relazione, una classe con più relazioni oppure più classi con una relazione.6 Un nodo inoltre descrive la corrispondenza tra elementi del c-cluster e dell’r-cluster mediante un insieme di corrisponden4 5 6 L’operazione di lettura è significativa solo per classi con chiave. Inoltre, per le classi di sola lettura non sono significative le operazioni di creazione, modifica e cancellazione. Più precisamente, ciascun elemento di un c-cluster è in corrispondenza con una classe dello schema a oggetti. Pertanto, è possibile che una stessa classe partecipi in più c-cluster, o addirittura che partecipi più volte nello stesso c-cluster. Stesse considerazioni valgono per gli r-cluster, che saranno introdotti tra breve. Attualmente il modello non prevede la possibilità di far corrispondere mediante un nodo più classi con più relazioni. In pratica, alcune corrispondenze complesse di quest’ultimo tipo possono essere rappresentate mediante gli archi. partecipazione imp {NK}{FK: impiegato} prog {NK}{FK: progetto} Partecipa * AIP Impiegato * -matricola {KEY} -cognome -stipendio {null} * progetti -nome -budget Risiede * codice {AK} denominazione budget dataInizio {null} NP impiegato impiegati progetto Progetto residenza 1 Comune {RO} Afferisce -nome {KEY} -provincia NI AID 1 dipartimento Dipartimento matricola {NK} cognome stipendio {null} comune provincia dip {FK: dipartimento} dipartimento codice {AK} nome div {FK:divisione} -nome -divisione divisione codice {AK} nome comune {null} ND Figura 3. Corrispondenza tra gli schemi delle Figure 1 e 2 ze tra attributi. Una corrispondenza tra attributi è una coppia formata da un attributo di una classe e un attributo di una relazione. La Figura 3 mostra una corrispondenza tra gli schemi di Figura 1 e 2, basata su tre nodi: un nodo NP che descrive la corrispondenza tra la classe Progetto e la relazione progetto, un nodo NI che descrive la corrispondenza tra le classi Impiegato e Comune e la relazione impiegato e un nodo ND che descrive la corrispondenza tra la classe Dipartimento e le relazioni dipartimento e divisione. Il nodo NP descrive la corrispondenza tra una classe (Progetto) e una relazione (progetto); evidentemente, sia la classe che la relazione sono primarie nel nodo. La loro corrispondenza è basata sulle corrispondenze tra attributi (Progetto.nome, progetto.denominazione) e (Progetto.budget, progetto.budget). Il nodo NP descrive una corrispondenza totale tra una classe e una relazione: ciascun oggetto della classe viene rappresentato da una tupla della relazione. La corrispondenza è tra una classe senza chiave e una relazione con chiave artificiale. Tutti gli attributi della classe sono coinvolti dalla corrispondenza. Viceversa, non tutti gli attributi della relazione sono coinvolti dalla corrispondenza. Questa cor- rispondenza permette di gestire, ad esempio, la creazione di un nuovo Progetto mediante l’inserimento di una nuova tupla in progetto; questa tupla prende il valore di progetto.denominazione e progetto.budget dagli attributi dell’oggetto, sulla base della corrispondenza; inoltre, il valore di progetto.codice viene generato automaticamente e il valore di progetto.dataInizio rimane nullo. Il nodo NI descrive invece la corrispondenza tra due classi (Impiegato e Comune) legate da una associazione (Risiede) e una relazione (impiegato). In questo nodo la classe primaria è Impiegato. In pratica, a ciascun oggetto della classe primaria Impiegato può essere associato (mediante l’associazione Risiede) anche un oggetto della classe secondaria Comune (il Comune in cui Risiede l’Impiegato). Ciascuna tupla di impiegato viene usata per rappresentare un oggetto Impiegato insieme all’oggetto Comune ad esso associato, nonché al collegamento di tipo Risiede tra questi due oggetti. In questo nodo, in cui la classe primaria è con chiave, la corrispondenza è basata sulle corrispondenze tra gli attributi chiave della classe primaria e della relazione primaria (Impiegato.matricola, impiegato.matricola), nonché sulle corrispondenze tra attributi (Impiegato.cognome, impiegato.cognome), (Impiegato.stipendio, impiegato.stipendio), (Comune.nome, impiegato.comune) e (Comune.provincia, impiegato.provincia). Infine, il nodo ND descrive la corrispondenza tra una classe (Dipartimento) e due relazioni (dipartimento e divisione); la relazione primaria è dipartimento. In pratica, ciascun oggetto Dipartimento viene rappresentato da una tupla di dipartimento e da una tupla di divisione, legate da una integrità referenziale. La corrispondenza è basata sulle corrispondenze tra attributi (Dipartimento.nome, dipartimento.nome) e (Dipartimento.divisione, divisione.nome). Quest’ultima corrispondenza ha senso solo con riferimento all’integrità referenziale tra la relazione primaria dipartimento e la relazione secondaria divisione dell’rcluster. Infatti, questo nodo permette di rappresentare nella corrispondenza sia le due relazioni che il vincolo di integrità referenziale che sussiste tra di esse. In generale, non tutte le corrispondenze sono corrette. Ad esempio, se la classe primaria di un nodo è con chiave, allora è necessario che i suoi attributi chiave siano posti in corrispondenza con gli attributi chiave della relazione primaria del nodo. Viceversa, se la classe primaria è senza chiave, allora la relazione primaria del nodo deve essere con chiave artificiale. Il problema della correttezza delle corrispondenze sarà discusso nella Sezione 4. Una corrispondenza M2 ORM2 può contenere anche degli archi; intuitivamente, questi permettono di rappresentare corrispondenze ed elementi che non trovano spazio nei nodi, e in particolare ulteriori associazioni e integrità referenziali, a talvolta anche delle relazioni. Ciascun arco di una corrispondenza descrive una relationship tra una coppia di nodi, e può essere di tipo uno-a-uno, uno-a-molti e molti-a-molti. Un arco è basato su una corrispondenza tra classi e una tra relazioni. Una corrispondenza tra classi descrive la corrispondenza tra le classi primarie dei c-cluster dei nodi collegati dall’arco, ed è basata sui ruoli navigabili di una associazione tra le due classi. In pratica, i ruoli vengono implementati da attributi riferimento (per la navigazione a-uno) e/o da attributi collezioni a riferimenti (per la navigazione a-molti). Dato che una associazione può essere unidirezionale o bidirezionale, viene coinvolto un solo attributo nel primo caso e una coppia di attributi nel secondo caso. Una corrispondenza tra relazioni descrive la corrispondenza tra le relazioni primarie degli r-cluster dei nodi collegati dall’arco, ed è basata sull’insieme degli attributi che implementano la relationship tra le due relazioni mediante integrità referenziali, che coinvolgono eventualmente anche altre relazioni. Un arco raggruppa una corrispondenza tra classi e una tra relazioni, stabilendo una relationship uno-a-uno, uno-a-molti o molti-a-molti tra le istanze descritte da una coppia di nodi. Ad esempio, la corrispondenza di Figura 3 tra gli schemi delle Figure 1 e 2 contiene due archi: AID per l’associazione uno-a-molti tra Impiegato e Dipartimento e AIP per l’associazione molti-a-molti tra Impiegato e Progetto. L’arco AID tra NI e ND descrive la relationship uno-a-molti tra impiegati e dipartimenti. Questa relationship è rappresentata dalla corrispondenza [Impiegato.dipartimento, Dipartimento.impiegati] tra le classi Impiegato e Dipartimento e dalla corrispondenza [impiegato.dip] tra le relazioni impiegato e dipartimento. In pratica, questo arco fa corrispondere l’associazione Afferisce tra Impiegato e Dipartimento con l’integrità referenziale tra impiegato e dipartimento. L’arco AIP tra NI e NP descrive la relationship molti-a-molti tra impiegati e progetti. Esso è basato sulla corrispondenza (unidirezionale) [Impiegato.progetti] tra le classi Impiegato e Progetto e sulla corrispondenza [partecipazione.imp, partecipazione.prog] tra le relazioni impiegato e progetto. In pratica, questo arco fa corrispondere l’associazione Partecipa tra Impiegato e Progetto con le integrità referenziali tra impiegato e progetto memorizzate nelle tuple della relazione partecipazione. 4 Correttezza delle corrispondenze Nella sezione precedente M2 ORM2 è stato utilizzato come strumento sintattico per rappresentare corrispondenze. Le corrispondenze hanno anche una semantica, che descrive come sia possibile realizzare le operazioni su oggetti e collegamenti dello schema a oggetti mediante operazioni sulle relazioni dello schema relazionale. Tuttavia, non tutte le corrispondenze che possono essere descritte da M2 ORM2 sono corrette. Intuitivamente, una corrispondenza è corretta se consente effettivamente di realizzare le operazioni CRUD su oggetti e collegamenti. Viceversa, è possibile dire che una corrispondenza è non corretta se le operazioni su oggetti e collegamenti possono causare anomalie. Nel resto di questa sezione vengono identificate le possibili anomalie provocate da corrispondenze non corrette, nonché alcune categorie di condizioni adeguate allo studio della correttezza delle corrispondenze M2 ORM2 . Si consideri una sequenza di operazioni CRUD su oggetti e collegamenti che complessivamente trasforma una istanza valida dello schema a oggetti in un’altra istanza valida, ovvero in cui tutti i vincoli di integrità imposti dallo schema sono rispettati. Una corrispondenza non corretta può causare le seguenti anomalie nell’esecuzione di una tale sequenza di operazioni: – le anomalie di creazione si verificano se lo schema relazionale non è in grado di gestire la creazione di oggetti da una qualche classe (non di sola lettura); le anomalie di creazione si verificano ad esempio se la classe non viene rappresentata nella corrispondenza, se non tutti i suoi attributi sono messi in corrispondenza con attributi dello schema relazionale, se non tutti i suoi attributi chiave sono messi in corrispondenza opportuna con attributi chiave dello schema relazionale; – le anomalie di lettura sono relative all’impossibilità di identificare univocamente oggetti da classi con chiave mediante la chiave; queste anomalie sono legate, ad esempio, ad errate corrispondenze tra attributi chiave delle classi e attributi chiave di relazioni; – le anomalie di aggiornamento impediscono di gestire la modifica di attributi di oggetti (non di sola lettura); – le anomalie di cancellazione impediscono di gestire la cancellazione di oggetti (non di sola lettura). In modo simile, è possibile identificare anomalie relative alla formazione di collegamenti, nonché alla loro navigazione, modifica e rottura. Le anomalie possono essere causate da corrispondenze tra elementi non corrette oppure da rappresentazioni non corrette di vincoli di integrità. Un caso del primo tipo si verifica ad esempio se le corrispondenze tra elementi sono incomplete, ovvero se non tutti gli elementi dello schema a oggetti (classi, associazioni e attributi) sono stati messi in corrispondenza con elementi dello schema relazionale. In effetti, ciascuna classe deve occorrere in almeno un nodo, e similmente gli attributi delle classi devono normalmente occorrere in almeno una corrispondenza tra attributi. Inconsistenze nella rappresentazione di vincoli di integrità possono avvenire in molti modi. Ad esempio, relativamente ai vincoli di chiave, è necessario che gli attributi chiave delle classi primarie con chiave siano posti in corrispondenza con attributi chiave delle corrispondenti relazioni primarie; viceversa, classi primarie senza chiave vanno poste in corrispondenza con relazioni con chiave artificiale. Come ulteriore esempio, relativo a vincoli di integrità referenziale, in un nodo che fa corrispondere una classe a più relazioni, gli attributi non chiave della classe devono essere posti in corrispondenza con attributi non chiave delle relazioni, e le integrità referenziali verso relazioni secondarie devono essere realizzate mediante chiavi artificiali. Quelle descritte sono condizioni necessarie per la correttezza delle corrispondenze M2 ORM2 . D’altra parte, una implementazione deve fissare condizioni sufficienti per gestire effettivamente le corrispondenze considerate corrette. In pratica, nei sistemi esistenti le condizioni utilizzate sono molto restrittive. Uno degli obiettivi di questa ricerca è identificare condizioni quanto più possibili permissive rispetto alle quali le corrispondenze siano semanticamente significative. 5 Discussione La letteratura “professionale” delle basi di dati e quella dei pattern languages è ricca di contributi su come gestire classi persistenti mediante basi di dati relazio- nali [1,5,9,14]. La maggior parte dei lavori descrive l’O/R mapping, una sorta di progettazione logica [2] effettuata a partire da uno schema a oggetti anziché da uno schema entità-relazione. Ma come è stato già detto nell’Introduzione, l’O/R mapping sostiene la definizione di una base di dati di supporto a una singola applicazione, e non condivisa tra molte applicazioni, essendo quest’ultima una delle motivazioni principali per gestire dati persistenti mediante un DBMS. Anche la letteratura scientifica delle basi di dati si è occupata di questo argomento. Persistence [13] è un sistema per l’O/R mapping. Gateway [18] è un sistema per la gestione di oggetti persistenti mediante base di dati relazionali basato sull’approccio meet in the middle; tuttavia, il lavoro non fornisce dettagli sul modello di corrispondenza impiegato. EBO [19] è un sistema per l’R/O mapping, che fornisce alcune funzionalità per le corrispondenze meet in the middle; anche in questo caso manca una descrizione del modello delle corrispondenze. Il problema della descrizione e dell’analisi delle corrispondenze tra schemi è di interesse anche nei lavori sulla trasformazione dei dati [7] e sull’integrazione di dati [8]. La nozione di corrispondenza usata in questo lavoro è ispirata a quella proposta in [3] nel contesto del model management. La Tabella 1 confronta M2 ORM2 con alcuni standard e sistemi commerciali oppure open source per la gestione trasparente della persistenza di oggetti. JDO [10] è uno standard per la gestione persistente di oggetti Java. OJB [17] è un progetto open-source Apache, che offre una implementazione delle API di ODMG che permettono di interagire con gli oggetti persistenti come se fossero memorizzati in una base di dati a oggetti ODMG [6]; il progetto prevede anche una futura implementazione delle API di JDO. JDX [11] offre caratteristiche di O/R mapping simili a quelli di OJB; gli oggetti persistenti vanno acceduti mediante delle API proprietarie. JRELAY [12] è una implementazione di JDO, che consente tutti e tre gli approcci di mapping, ma con varie limitazioni. In futuro, è prevista da una parte l’implementazione di un framework per la gestione della persistenza di oggetti basato su M2 ORM2 . Da un punto di vista teorico, è inoltre previsto lo studio di estensioni del modello (ad esempio, per gestire l’ereditarietà, classi e attributi transienti, ulteriori vincoli di integrità, ma anche eterogeneità schematiche [16]) nonché di caratterizzazioni più precise della correttezza di corrispondenze M2 ORM2 . Riferimenti bibliografici 1. S.W. Ambler. The fundamentals of mapping objects to relational databases. White Paper, http://www.agiledata.org, 2003. 2. P. Atzeni, S. Ceri, S. Paraboschi e R. Torlone. Basi di dati. Modelli e linguaggi di interrogazione. McGraw-Hill, 2002. 3. P.A. Bernstein, A.Y. Halevy, and R.A. Pottinger. A vision for the management of complex models. ACM Sigmod Record, 29(4):55–63, 2000. 4. G. Booch, J. Rumbaugh, and I. Jacobson. The Unified Modeling Language User Guide. Addison-Wesley, 1999. Tabella 1. Confronto con altri modelli e strumenti Caratteristica O/R mapping (forward engineering) R/O mapping (reverse engineering) Meet in the middle Una classe una relazione Una classe più relazioni con integr. referenz. Una classe più relazioni con partiz. verticale Più classi una relazione Più classi più relazioni Classi con chiave Classi senza chiave Classi di sola lettura Attributo di classe mappato in più relazioni Relationship uno-a-uno Relationship uno-a-molti Relationship molti-a-molti senza attributi Relationship molti-a-molti con attributi Relationship molti-a-molti con attrib. selettivo a b JDO si n/a n/a n/a n/a n/a n/a n/a si si no n/a n/a n/a n/a n/a n/a OJB JRELAY JDX M2 ORM2 si si si no si si si no si si si si si si si si sia si no si no no no si no no si si no no no no si si si si no si no si no no no si no no no si si si si si si si si si si si no si no no no sib no no no sib Si, ma non implementato. Si, ma non discusso qui. 5. K. Brown and B.G. Whitenack. Crossing Chasms: A pattern language for objectRDBMS integration. In Pattern Languages of Program Design 2, 1996. 6. R.G.G. Cattell et al. The Object Data Standard: ODMG 3.0. MK, 2000. 7. Data Transformations. S.ı. of the IEEE Bull. on Data Engineering, 22(1), 1999. 8. Integration management. S.ı. of the IEEE Bull. on Data Engineering, 25(3), 2002. 9. M.L. Fussell. Foundations of object relational mapping. White Paper, http://www.chimu.com, 1997. 10. Java Data Objects. http://www.jdocentral.com. 11. JDX. http://www.softwaretree.com/. 12. JRELAY. http://www.objectindustries.com/. 13. A.M. Keller, R. Jensen, and S. Agrawal. Persistence Software: Bridging objectoriented programming and relational databases. In ACM SIGMOD International Conf. on Management of Data, pages 523–528, 1993. 14. W. Keller. Mapping object to tables: A pattern language. In European Conf. on Pattern Languages of Programming, 1997. 15. C. Larman. Applying UML and Patterns. An introduction to object-oriented analysis and design and the Unified Process. Prentice Hall PTR, 2002. 16. R.J. Miller. Using schematically heterogeneous structures. In ACM SIGMOD International Conf. on Management of Data, pages 189–200, 1998. 17. ObJect relational Bridge. http://db.apache.org/ojb/. 18. J.A. Orenstein and D.N. Kamber. Accessing a relational database through an object-oriented database interface. In 21st Int. Conf. on VLDB, 702–705, 1995. 19. J.A. Orenstein. Supporting retrievals and updates in an object/relational mapping system. IEEE Bull. on Data Engineering, 20(1):50–54, 1999. 20. Torque. http://db.apache.org/torque/.