Hibernate 6 Enum관련

존스노우·2024년 2월 19일
0

기타

목록 보기
6/7

보통 Spring data. Jpa를 사용하면

ddl-auto: validate

  • 이런식의 옵션을 준다.
@Column(length = 10)
@Enumerated(EnumType.STRING)
private MailStatus status;
  • 컬럼 하나를 이렇게 주고. 프로젝트를 실행시켰는데.

    found [varchar (Types#VARCHAR)], but expecting [enum ('activated','draft')

  • 이런에러가 났다. 왜 그럴까?
Enumerated types
We included Java enums on the list above. An enumerated type is considered a sort of basic type, but since most databases don’t have a native ENUM type, JPA provides a special @Enumerated annotation to specify how the enumerated values should be represented in the database:

by default, an enum is stored as an integer, the value of its ordinal() member, but

if the attribute is annotated @Enumerated(STRING), it will be stored as a string, the value of its name() member.

//here, an ORDINAL encoding makes sense
@Enumerated
@Basic(optional=false)
DayOfWeek dayOfWeek;

//but usually, a STRING encoding is better
@Enumerated(EnumType.STRING)
@Basic(optional=false)
Status status;
In Hibernate 6, an enum annotated @Enumerated(STRING) is mapped to:

a VARCHAR column type with a CHECK constraint on most databases, or

an ENUM column type on MySQL.

Any other enum is mapped to a TINYINT column with a CHECK constraint.

JPA picks the wrong default here. In most cases, storing an integer encoding of the enum value makes the relational data harder to interpret.

Even considering DayOfWeek, the encoding to integers is ambiguous. If you check java.time.DayOfWeek, you’ll notice that SUNDAY is encoded as 6. But in the country I was born, SUNDAY is the first day of the week!

So we prefer @Enumerated(STRING) for most enum attributes.
  • 출처 : https://docs.jboss.org/hibernate/orm/6.3/introduction/html_single/Hibernate_Introduction.html#enums

  • 대충 요약하면..

  • 보통 @Enumerated(EnumType.STRING) 어노테이션이 붙어 있다면, 이는 문자열로 저장

  • 이 문자열은 열겨형의 name() 메서드가 반환하는값

  • 열거형 값을 디비에 저장 방식이 기본 설정이 이전보다 . 더 엄격 해짐

  • 이 내용만 있고 나머지설명은 그냥 @Enumerated(STRING) 하면 스트링 형식으로 저장된다..

  • 그냥 디비 저장방식이 기본설정보다 엄격해졌다는 내용외엔 뭐가 없다..

  • https://discourse.hibernate.org/t/hibernate-6-wrong-column-type-encountered-for-enum-postgresql-int4-vs-smallint/7518

  • 하이버네이트 포럼에서도 다들 기본설정이 엄격해져서 모두 명시적으로 타입을지정해서

  • 해결했다는 내용만나오고 . 참어렵다.

  • 그냥 이렇게 이해하면 될까?

  • @Enumerated 없이는 enum형은 정수 값을 저장

  • @Enumerated(EnumType.String) 선언하면 이전버전에는 엄격하지않아서

  • String으로 저장됬으니 버전업이되면서 엄격하게. 타입을 검사하면서

  • 명시적으로 안전하게 타입 을 지정해줘야된다..?

해결

  • @Column(length = 10, columnDefinition = "varchar")
    @Enumerated(EnumType.STRING)
    private MailStatus status;
  • 명시적으로 디비에게 명시적으로 지정.

추가

Datatype for enums
Hibernate 6.1 changed the implicit SQL datatype for mapping enums from TINYINT to SMALLINT to account for Java supporting up to 32K enum entries which would overflow a TINYINT. However, almost no one is developing enums with that many entries. Starting in 6.2, the choice of implicit SQL datatype for storing enums is sensitive to the number of entries defined on the enum class. Enums with more than 128 entries are stored as SMALLINT implicitly, otherwise TINYINT is used.
NOTE
On MySQL, enums are now stored using the ENUM datatype by default

  • https://docs.jboss.org/hibernate/orm/6.2/migration-guide/migration-guide.html#ddl-implicit-datatype-enum

  • 하이버네이트 6.2부터는 매핑 검증방식이 조금 더 엄격해졌고,

  • 그 중 MySQL DB인 경우, 기본 Java Enum 매핑은 MySQL의 ENUM 타입을 사용하도록 전략이 변경되었기에,

  • 명시적으로 컬럼 데피니션 혹은 조금 더 간결하게는 @JdbcTypeCode(SqlTypes.VARCHAR) 어노테이션으로 DB의 타입을 명시해야 된다.

  • 데이터베이스 설계와 Hibernate 엔티티 사이의 일관성을 유지하고, 예상치 못한 타입 불일치로 인한 오류를 방지하는 데 도움

내가 이해 한바

  • 그러니까 mysql 열거형저장방식이 디폴트로 6.2부터 되잇으니
    jpa컬럼에서 varchar로 저장하려면 명시적으로 지정해줘야 되고,
    안그러면 디비만 varchar형식으로해놓으면 위에 같은 예외가일어나는 것?
profile
어제의 나보다 한걸음 더

0개의 댓글