Beskrivning

I föregående lektion såg du att Hibernate använder en speciell DTYPE VARCHAR-kolumn för att lagra namnet på en Entity-klass. En sådan kolumn kallas en diskriminator . Den används för att entydigt bestämma vilken klass som ska skapas för en given rad i databasen.

Du kan manipulera den här kolumnen med @DiscriminatorColumn -kommentaren . Exempel:

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

Enligt JPA-specifikationen kan en diskriminator ha följande typer:

  • STRÄNG
  • RÖDING
  • HELTAL

Men Hibernate låter dig utöka den här listan lite. Den stöder dessa Java-typer: String, char, int, byte, short, boolean.

Om vi ​​använder INTEGER-typen, hur kodar man då namnet på Entity-klassen i den? För detta används en annan anteckning - @DiscriminatorValue .

Titta på ett exempel:

@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 exemplet ovan sa vi till Hibernate att diskriminatorn kommer att använda kolumnen user_type, som kommer att lagra nummer. Om den lagrar värdet 1 betyder det att radtypen är Anställd, om 2 är lagrad så är radtypen Klient. Enkelt och vackert.

@DiscriminatorValue

Men det är inte allt. Du kan berätta för Hibernate hur man tolkar typen av en sträng när dess diskriminator är NULL.

Det är faktiskt väldigt enkelt. Du anger nullvärdet för @DiscriminatorValue- kommentaren . Till exempel, så här:

@DiscriminatorValue("null")

Klassexempel:

@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 sagt till Hibernate att alla tabellrader som har NULL i kolumnen user_type ska tolkas som ett objekt av typen User.

Men det är inte allt. Det finns ett annat intressant värde för @DiscriminatorValue-kommentaren.

Här är detta:

@DiscriminatorValue("not null")

Klassexempel:

@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 den här anteckningen sa vi till Hibernate att alla tabellrader med ett icke-NULL-värde i kolumnen user_type ska tolkas som ett objekt av typen User. Men detta är bara för fallet om en klass inte hittas som har det erforderliga antalet uttryckligen specificerat.

Så här kommer det att fungera för olika värderingar av diskriminatorerna:

  • 0 - skapa ett objekt av typen Användare
  • 1 - skapa ett objekt av typen Anställd
  • 2 - skapa ett objekt av typen Client
  • 3 - skapa ett objekt av typen Användare
  • 4 - skapa ett objekt av typen Användare

@Diskrimineringsformel

Men det är inte allt. För vår diskriminator kan vi ange en heltalsformel med vilken den kommer att beräkna värdena för @DiscriminatorValue- anteckningen .

Det finns en speciell anteckning för detta, den heter @DiscriminatorFormula .

Exempel:

@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;
}

Värdena som returneras av @DiscriminatorFormula kommer att jämföras av Hibernate med värdena som anges i @DiscriminatorValue- anteckningarna . Med den kan du skriva ganska komplexa scenarier:

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