venerdì 20 gennaio 2012

Impedance mismatch

Con il termine "impedance mismatch" si intendono le differenze di adattamento di un modello ad oggetti con il classico sistema relazionale di archiviazione dati.
Concetti come l'ereditarietà ad esempio, basilari nella programmazione ad oggetti, non sono presenti in un modello relazionale.
Con JPA sono possibili 3 strategie di "inheritance mapping", le descriviamo prendendo come un esempio la seguente gerarchia di classi volutamente semplificata:

public class Persona{
 public String nome;
public String cognome;
}


public class Studente extends Persona{
 public String matricola;
public int annoCorso;
}

public class Professore extends Persona{
public String materiaInsegnata;
}
  1. SINGLE TABLE (strategia di default per gli EJB 3.0)
  2. JOINED TABLES
  3. TABLE PER CLASS
SINGLE TABLE

Con questa strategia tutte le classi della scala gerarchica sono mappate ad un'unica tabella, che conterrà quindi l'insieme di tutti i dati e che chiameremo PERSONE.
Gli oggetti differenti sono individuati tramite una colonna di discriminazione, ad esempio nella nostra tabella potremo definirla TIPO_PERSONA char(1) e mapparla con il valore S se  Studente e P se professore.
Il modello di entità coinvolte sarà quindi di questo tipo:

@Entity
@Table(name="PERSONE")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TIPO_PERSONA",discriminatorType=DiscriminatorType.STRING,lenght=1)
public abstract class Persona{
.....
}


@Entity
@DiscriminatorValue(value="S")
public class Studente extends Persona{
....
}

@Entity
@DiscriminatorValue(value="P")
public class Professore extends Persona{
....
}

Si noti che la strategia viene mappata nella classe radice dell'albero gerarchico.
Il grosso svantaggio di questo approccio è il mancato sfruttamento delle potenzialità del database.


JOINED-TABLES

Con questo modello si sfruttano le potenzialità del dbms, inserendo i campi comuni in una tabella e legando le tabelle professore e studente con una relazione uno a uno.
Avremo quindi una struttura di questo tipo

Tabella Persona

ID_PERSONA(PK)
NOME
COGNOME
TIPO_PERSONA

Tabella Studente
ID_PERSONA(PK)
...(campi specifici)

Tabella Professore
ID_PERSONA(PK)
...(campi specifici)


Anche in questo caso è necessario avere il campo discriminatore, la struttura ad oggetti sarà la seguente (in grassetto le differenze rispetto al precedente esempio)



@Entity
@Table(name="PERSONE")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="TIPO_PERSONA",discriminatorType=DiscriminatorType.STRING,lenght=1)
public abstract class Persona{
.....
}


@Entity
@DiscriminatorValue(value="S")
@PrimaryKeyJoinColumn(name="ID_PERSONA")
public class Studente extends Persona{
....
}


@Entity

@DiscriminatorValue(value="P")
@PrimaryKeyJoinColumn(name="ID_PERSONA") 

public class Professore extends Persona{

....

}

Da un punto di vista del design questa scelta è sicuramente più elegante e generalmente consigliata.


TABLE-PER-CLASS

Con questa strategia sia la superclasse sia le sottoclassi hanno le loro tabelle di riferimento e non esistono relazioni tra le tabelle stesse.
In pratica le relazioni esistono solo sul modello ad oggetti mentre le tre tabelle lato DMBS non sono correlate. E' tuttavia molto più complicato eseguire query sugli oggetti e spesso bisogna ricorrere alle UNION, non molto efficienti.
Lato Java la situazione è la seguente:


@Entity

@Table(name="PERSONE")

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

public  class Persona{

.....

}





@Entity
 @Table(name="STUDENTE")

public class Studente extends Persona{

....

}



@Entity

@Table(name="PROFESSORE")

public class Professore extends Persona{

....

}

Questa strategia è la più confusionaria delle 3 e proprio per questo motivo per gli AS non è obbligatorio implementarla 

Nessun commento:

Posta un commento