描述

在上一课中,您看到 Hibernate 使用特殊的 DTYPE VARCHAR 列来存储实体类的名称。这样的列称为鉴别器。它用于明确确定为数据库中的给定行创建哪个类。

您可以使用@DiscriminatorColumn注释操作此列。例子:

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

根据 JPA 规范,鉴别器可以有以下类型:

  • 细绳
  • 字符
  • 整数

但是,Hibernate 允许您稍微扩展此列表。它支持这些 Java 类型:String、char、int、byte、short、boolean。

如果我们使用的是INTEGER类型,那么Entity类的名字怎么编码呢?为此,使用了另一个注解—— @DiscriminatorValue

看一个例子:

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

在上面的示例中,我们告诉 Hibernate 鉴别器将使用 user_type 列,该列将存储数字。如果存储值1,则表示行类型为Employee,如果存储2,则表示行类型为Client。简单而美丽。

@DiscriminatorValue

但这还不是全部。您可以告诉 Hibernate 在鉴别符为 NULL 时如何解释字符串的类型。

其实很简单。您为@DiscriminatorValue annotation指定空值。例如,像这样:

@DiscriminatorValue("null")

类示例:

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

我们已经告诉 Hibernate,任何在 user_type 列中具有 NULL 的表行都应该被解释为 User 类型的对象。

但这还不是全部。@DiscriminatorValue 注释还有另一个有趣的值。

这是这个:

@DiscriminatorValue("not null")

类示例:

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

通过这个注释,我们告诉 Hibernate 任何在 user_type 列中具有非 NULL 值的表行都应该被解释为 User 类型的对象。但这仅适用于未找到明确指定所需数量的类的情况。

对于鉴别器的不同值,它是这样工作的:

  • 0 - 创建用户类型的对象
  • 1 - 创建一个Employee类型的对象
  • 2 - 创建一个客户端类型的对象
  • 3 - 创建一个用户类型的对象
  • 4 - 创建一个用户类型的对象

@DiscriminatorFormula

但这还不是全部。对于我们的判别器,我们可以指定一个整数公式,它将通过该公式计算@DiscriminatorValue注释的值。

为此有一个特殊的注释,称为@DiscriminatorFormula

例子:

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

@DiscriminatorFormula返回的值将由 Hibernate 与@DiscriminatorValue注解中指定的值进行比较。有了它,你可以编写相当复杂的场景:

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