Descrizione

Nella lezione precedente, hai visto che Hibernate utilizza una speciale colonna DTYPE VARCHAR per memorizzare il nome di una classe Entity. Tale colonna è chiamata discriminatore . Viene utilizzato per determinare in modo univoco quale classe creare per una determinata riga nel database.

Puoi manipolare questa colonna con l' annotazione @DiscriminatorColumn . Esempio:

@DiscriminatorColumn(name="column_name",   discriminatorType = DiscriminatorType.INTEGER)

Secondo la specifica JPA, un discriminatore può avere i seguenti tipi:

  • CORDA
  • CAR
  • NUMERO INTERO

Tuttavia, Hibernate ti consente di espandere un po 'questo elenco. Supporta questi tipi Java: String, char, int, byte, short, boolean.

Se usiamo il tipo INTEGER, allora come codificare il nome della classe Entity in esso? Per questo, viene utilizzata un'altra annotazione: @DiscriminatorValue .

Guarda un esempio:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
@DiscriminatorValue("1")
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
@DiscriminatorValue("2")
class Client extends User {
   String address;
}

Nell'esempio sopra, abbiamo detto a Hibernate che il discriminatore utilizzerà la colonna user_type, che memorizzerà i numeri. Se memorizza il valore 1, significa che il tipo di riga è Dipendente, se 2 è memorizzato, il tipo di riga è Cliente. Semplice e bello.

@DiscriminatorValue

Ma non è tutto. Puoi dire a Hibernate come interpretare il tipo di una stringa quando il suo discriminatore è NULL.

In realtà è molto semplice. Si specifica il valore null per l' annotazione @DiscriminatorValue . Ad esempio, in questo modo:

@DiscriminatorValue("null")

Esempio di classe:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("null")
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}

Abbiamo detto a Hibernate che ogni riga di tabella che ha NULL nella colonna user_type dovrebbe essere interpretata come un oggetto di tipo User.

Ma non è tutto. C'è un altro valore interessante per l'annotazione @DiscriminatorValue.

Ecco questo:

@DiscriminatorValue("not null")

Esempio di classe:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("not null")
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}

Con questa annotazione, abbiamo detto a Hibernate che qualsiasi riga della tabella con un valore non NULL nella colonna user_type dovrebbe essere interpretata come un oggetto di tipo User. Ma questo è solo per il caso in cui non viene trovata una classe che abbia il numero richiesto specificato in modo esplicito.

Ecco come funzionerà per diversi valori dei discriminatori:

  • 0 - crea un oggetto di tipo Utente
  • 1 - crea un oggetto di tipo Dipendente
  • 2 - crea un oggetto di tipo Client
  • 3 - creare un oggetto di tipo Utente
  • 4 - creare un oggetto di tipo Utente

@DiscriminatorFormula

Ma non è tutto. Per il nostro discriminatore, possiamo specificare una formula intera in base alla quale calcolerà i valori per l' annotazione @DiscriminatorValue .

C'è un'annotazione speciale per questo, si chiama @DiscriminatorFormula .

Esempio:

@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type",   discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorFormula("case when ‘join’ is not null then 1 else 2 end")
@Entity
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
@DiscriminatorValue("1")
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
@DiscriminatorValue("2")
class Client extends User {
   String address;
}

I valori restituiti da @DiscriminatorFormula verranno confrontati da Hibernate con i valori specificati nelle annotazioni @DiscriminatorValue . Con esso, puoi scrivere scenari piuttosto complessi:

@DiscriminatorFormula(
           	"case when address is not null " +
           	"then 'Client' " +
           	"else (" +
           	"   case when occupation is not null " +
           	"   then 'Employee' " +
           	"   else 'Unknown' " +
           	"   end) " +
           	"end "
)