Beskrivelse
I forrige leksjon så du at Hibernate bruker en spesiell DTYPE VARCHAR-kolonne for å lagre navnet på en Entity-klasse. En slik kolonne kalles en diskriminator . Den brukes til entydig å bestemme hvilken klasse som skal opprettes for en gitt rad i databasen.
Du kan manipulere denne kolonnen med @DiscriminatorColumn -kommentaren . Eksempel:
@DiscriminatorColumn(name="column_name", discriminatorType = DiscriminatorType.INTEGER)
I henhold til JPA-spesifikasjonen kan en diskriminator ha følgende typer:
- STRING
- CHAR
- HELTAL
Imidlertid lar Hibernate deg utvide denne listen litt. Den støtter disse Java-typene: String, char, int, byte, short, boolean.
Hvis vi bruker INTEGER-typen, hvordan koder vi navnet på Entity-klassen i den? Til dette brukes en annen merknad - @DiscriminatorValue .
Se på et eksempel:
@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;
}
I eksemplet ovenfor fortalte vi Hibernate at diskriminatoren vil bruke kolonnen user_type, som vil lagre tall. Hvis den lagrer verdien 1, betyr det at radtypen er Employee, hvis 2 er lagret, så er radtypen Client. Enkelt og vakkert.
@DiscriminatorValue
Men det er ikke alt. Du kan fortelle Hibernate hvordan du skal tolke typen av en streng når diskriminatoren er NULL.
Det er faktisk veldig enkelt. Du spesifiserer nullverdien for @DiscriminatorValue- kommentaren . For eksempel slik:
@DiscriminatorValue("null")
Klasseeksempel:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("null")
@Entity
class User {
int id;
String name;
LocalDate birthday;
}
Vi har fortalt Hibernate at enhver tabellrad som har NULL i user_type-kolonnen skal tolkes som et objekt av typen User.
Men det er ikke alt. Det er en annen interessant verdi for @DiscriminatorValue-kommentaren.
Her er dette:
@DiscriminatorValue("not null")
Klasseeksempel:
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="user_type", discriminatorType = DiscriminatorType.INTEGER)
@DiscriminatorValue("not null")
@Entity
class User {
int id;
String name;
LocalDate birthday;
}
Med denne merknaden fortalte vi Hibernate at enhver tabellrad med en verdi som ikke er NULL i kolonnen user_type skal tolkes som et objekt av typen User. Men dette er bare for tilfellet hvis en klasse ikke er funnet som har det nødvendige antallet eksplisitt spesifisert.
Slik vil det fungere for ulike verdier til diskriminatorene:
- 0 - opprett et objekt av typen Bruker
- 1 - opprett et objekt av typen Ansatt
- 2 - opprett et objekt av typen Klient
- 3 - opprett et objekt av typen Bruker
- 4 - opprett et objekt av typen Bruker
@DiskriminatorFormula
Men det er ikke alt. For diskriminatoren vår kan vi spesifisere en heltallsformel som den vil beregne verdiene for @DiscriminatorValue- kommentaren med .
Det er en spesiell merknad for dette, den heter @DiscriminatorFormula .
Eksempel:
@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;
}
Verdiene som returneres av @DiscriminatorFormula vil bli sammenlignet av Hibernate med verdiene spesifisert i @DiscriminatorValue- kommentarene . Med den kan du skrive ganske komplekse scenarier:
@DiscriminatorFormula(
"case when address is not null " +
"then 'Client' " +
"else (" +
" case when occupation is not null " +
" then 'Employee' " +
" else 'Unknown' " +
" end) " +
"end "
)