인프런 커뮤니티 질문&답변

임준호님의 프로필 이미지

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

@Enumerated와 hibernate 타입 검증 관련 해결을 어떻게 해야할지 모르겠습니다.

작성

·

3.8K

·

수정됨

4

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? 예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예
3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예

 

안녕하세요 강의에서 설명해주신 대로 따라하려고 했습니다.

단 , ddl-auto : create 대신 미리 SQL 문으로 테이블을 생성해놓고 ddl-auto: validate로 실행시 에러가 납니다. 이는 실제로 배운 것을 사용할 수 없는 아주 치명적인 부분이라고 생각하여 질문을 드립니다.

 

[문제 설명]

강의에서 설명해주신대로 위와 같이 Enumerated 를 사용하여 status 를 정의 하였습니다.
말씀해주신대로 value = EnumType.STRING을 사용했습니다.

UserStatus 는 당연히 enum 타입으로 했구요.

@Column(name = "status", length = 32) @Enumerated(value = EnumType.STRING) 
private UserStatus status;



이때 status 가 있는 테이블은 아래와 같은 SQL문으로 생성하였습니다.
VARCHAR(255)로 생성한 점을 자세히 봐주세요!
dbms: MySQL

CREATE TABLE user
(
    `id`                 BIGINT          NOT NULL    AUTO_INCREMENT,
    `status`             VARCHAR(255)     NOT NULL  check (status in ('CREATED', 'WITHDRAW')),
    PRIMARY KEY (id)
);

 

 

또한 application-yml 에는 아래와 같이 ddl-auto 를 validate 로 하였습니다.

jpa:
  hibernate:
    ddl-auto: validate
  properties:
    hibernate:
      format_sql: true
      show-sql: true

 

 하지만 이를 실행하면 아래와 같은 status의 타입 오류 에러가 나옵니다.

Schema-validation: wrong column type encountered in column [status] in table [user]; found [varchar (Types#VARCHAR)], but expecting [enum ('created','withdraw') (Types#ENUM)]

이는 db의 status 의 타입이 enum 이길 기대했지만 실제로는 VARCHAR이기 때문에 에러가 발생한다는 것입니다. (ddl-auto의 validate에 의해 검증 수행)



MySQL에서 타입에 enum을 적용하면 해결되지만 쓰는 것을 최대한 지양해야 한다고 알고 있습니다.

따라서 mysql 의 status 컬럼의 타입을 enum 대신 column 타입을 varchar(255)로 두고 사용하려고하는데 위와 같은 에러가 나서 실행이 되지 않습니다.
ddl-auto : none 으로 설정하면 임시적으로 실행은 할 수 있지만 validate 로 검증을 항상 진행하려고 합니다.

 

 

[질문 내용]


1. mysql의 타입을 varchar로 두고, ddl-auto: validate 를 사용하면서 에러 없이 실행할 수 있는 방법이 궁금합니다.


2. ddl-auto : create로 하게 되면 자동 생성되는 sql문에서는 status에 enum 대신
create table user (

id bigint not null,

status varchar(255) check (status in ('CREATED', 'WITHDRAW')),

primary key (id)

)
위처럼 varchar로 column 속성을 주면서 validate 할때만 에러가 나는것이 이상한 것 같은데 왜 그럴까요?

3. 이를 현업에서는 어떻게 해결하고 계신지 궁금합니다.

답변 2

1

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 임준호님

다음과 같이 columnDefinition을 사용하시면 됩니다.

    @Column(columnDefinition = "varchar(255)")
    @Enumerated(EnumType.STRING)    // 무조건 STRING으로 사용
    private OrderStatus status; // 주문상태 [ORDER, CANCEL]

감사합니다.

0

I think you can use STRING type for Enumerated annotation, and then use @Enumerated(EnumType.STRING) annotation to map the enum values to their names. This way, you can avoid the problems caused by ORDINAL type, such as changing the enum order or adding new enum values. However, you still need to validate the input values, because the user can enter anything that is a string. You can use @NotNull annotation to prevent null values, and then use @Size annotation to limit the input values to a certain length. For example, @Size(min = 4, max = 5). This way, you can reject the input values that are too short or too long. You can also use @Pattern annotation to check if the input values match a regular expression. For example, @Pattern(regexp = "ADMIN|USER"). This way, you can reject the input values that are not ADMIN or USER.

retro bowl