설명

이전 학습에서 Hibernate가 Entity 클래스의 이름을 저장하기 위해 특별한 DTYPE VARCHAR 열을 사용하는 것을 보았습니다. 이러한 열을 discriminator 라고 합니다 . 데이터베이스의 주어진 행에 대해 생성할 클래스를 명확하게 결정하는 데 사용됩니다.

@DiscriminatorColumn 주석을 사용하여 이 열을 조작할 수 있습니다 . 예:

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

JPA 사양에 따르면 판별자는 다음 유형을 가질 수 있습니다.

  • 정수

그러나 Hibernate를 사용하면 이 목록을 약간 확장할 수 있습니다. String, char, int, byte, short, boolean과 같은 Java 유형을 지원합니다.

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

위의 예에서 우리는 판별자가 숫자를 저장할 user_type 열을 사용할 것이라고 Hibernate에 알렸습니다. 값 1을 저장하면 행 유형이 Employee이고 2가 저장되면 행 유형이 Client임을 의미합니다. 간단하고 아름답습니다.

@DiscriminatorValue

하지만 그게 다가 아닙니다. 판별자가 NULL일 때 문자열의 유형을 해석하는 방법을 Hibernate에게 알릴 수 있습니다.

실제로 매우 간단합니다. @DiscriminatorValue 주석 에 대해 null 값을 지정합니다 . 예를 들면 다음과 같습니다.

@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 유형의 객체로 해석되어야 한다고 말했습니다. 그러나 이는 필요한 번호가 명시적으로 지정된 클래스를 찾을 수 없는 경우에만 해당됩니다.

이것은 discriminators의 다른 값에 대해 작동하는 방식입니다.

  • 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 "
)