inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

호돌맨의 요절복통 개발쇼 (SpringBoot, Vue.JS, AWS)

@NotBlank 와 @Id 의 불편한 동거?

1027

jcknow

작성한 질문수 5

2

오늘도 호돌님의 강의를 베이스로 이것저것 만들던중

아래와 같은 에러를 발생시킵니다. 

 

--------------------------------------------------------------------------------

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction

 

at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:571)

at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743)

at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)

at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)

------------------------------------------------------------------------------------------------------------

 

결국 초기화 시키고 다시 조합해 나가던중 

NotBlank 때문임을 발견합니다. (주석처리해둠)

 

  @Id
@Column(name = "member_id")
// @NotBlank
private Long member_id;

 

저는 선의의 마음으로 Id도 꼭 필요한 값이야!

를 선언하고 NotBlank를 썼는데, 

그 마음을 부정당한 느낌이라 스프링에 매우 섭섭합니다. 

 

이유를 알면 좀만 덜 섭섭할거 같은데 어떻게 공부해야 사연을 알수 있을까요??

 

암튼 불철주야 감사합니다 ㅇㅇd

aws vuejs spring-boot JPA Spring Security

답변 1

5

호돌맨

안녕하세요. 호돌맨입니다.
질문을 남겨주셔서 감사합니다.

1. 재현과정

  1. 아래와 같은 소스일때 발생하는 오류

        @Id
        @Column(name = "id")
        @NotBlank
        private Long id;
    ids for this class must be manually assigned before calling save(): com.hodolog.api.domain.Post; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.hodolog.api.domain.Post
    org.springframework.orm.jpa.JpaSystemException: ids for this class must be manually assigned before calling save(): com.hodolog.api.domain.Post; nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): com.hodolog.api.domain.Post
  2. @GeneratedValue를 넣은경우 발생하는 오류

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @NotBlank
    private Long id;
    HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.Long'. Check configuration for 'id'
    javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.Long'. Check configuration for 'id'
  3. 왜 오류가 다를까 생각해보니.. 수강민수께서는 id를 직접 set 해줬을거라 생각했습니다. 저도 Post.id를 직접 지정해봤습니다.
    역시! 수강민수님과 같은 오류가 발생했네요!

        @Id
        @Column(name = "id")
        @NotBlank
        private Long id;
    public void write(PostCreate postCreate) {
            Post post = Post.builder()
                    .title(postCreate.getTitle())
                    .content(postCreate.getContent())
                    .build();
    
            post.setId(100L); // id를 100으로 설정함
    
            postRepository.save(post);
        }
    Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
    org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction

2. 생각해보기

그렇다면 왜 오류가 발생했을까요?
힌트는 1-2에 있습니다.

그 이유는 바로... 두구두구두구...!!

그렇습니다! Long을 갖고 @NotBlank 검증을 할 수 없다는거죠!
그렇다면 @NotBlank가 어디에 쓰이는지 생각해볼 필요가 있습니다. (참고링크: https://sanghye.tistory.com/36)

그렇죠! @NotBlank는 null, "", " "와 같이 주로 String 타입을 검증하는데 쓰입니다.
문자열 검증 방식을 숫자타입에 적용하려고 하니 JPA가 개빢칠만합니다.

그렇다면 Long타입에 맞는 Validator를 넣으면 해결 될까요? 숫자에 맞는 검증 언노테이션은 뭔가 있을까요?!
'최소! 최대!' 바로 @Min, @Max등이 있겠죠?

저는 @Min을 아래와같이 사용해봤습니다.

@Id
@Column(name = "id")
@Min(1) // id가 1보다 큰지확인함 (테스트 케이스에서는 100으로 설정했습니다.)
private Long id;

야호! 정상적으로 통과!
수강민수님의 의도라면 @NotNull을 써보는 게 어떨까요?

3. 어떻게 알아냄?

아무튼 그건 그렇고!! 그렇다면 이런 오류는 과연 어떻게 알아내야할까?
사실 Intellij에 올라온 Exception 콘솔에 스크롤을 쭉 내려보면 Exception stack trace로 가 잡혀있습니다.

Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
... 생략
... 생략
UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.NotBlank' validating type 'java.lang.Long'. Check configuration for 'id'

image
현재 발생한 예외(TransactionException)이 어떤 예외를 쳐 맞고 쭉~ 쌓이게 되었는지! 보이는거죠!
그렇기 때문에 콘솔을 확인하실때는 현재 예외뿐만 아니라
스크롤을 쭉~~ 내리셔서 어떤 오류로 부터 예외가 전파되었는지 확인하면! 내일은 나도 개발 짱!

감사합니다.

0

jcknow

아니, 그냥 힌트만 달라고 했는데 아얘 1강을 만드시면 이거 어쩝니까.........

이런다고 감사할줄 아신다면 그건 크나큰 오예입니다.

그랜절 올립니다 감사합니다

근데 그거 아십니까? 저도 제가 Id를 set하는 천인공로할 짓을 했다는걸 이걸 보고 알았습니다. ㄷㄷ

(정확히는 testcase만지작 거리다 set질을 하려 했군요...)

무의식에서나마 이런짓을 하는걸 보니 전 아직 멀었나봅니다.

다시한번 ㅅ 잡고 반성하며 강의한번 더 듣겠습니다.

Deprecated 관련 사항들

0

128

2

깃헙 collaboator 초대 관련

0

104

1

강의 듣다가 도커 이미지 생성시 각각도 가능하나 그렇게 사용하는데가 많은지 모르겠다라는 말을 듣고 남김니다

0

171

2

logout 후에 login 페이지 이동은 어디서 시켜주는건가요?

0

243

1

다중 데이터를 삭제 할 때

0

293

2

querydsl Q class 이슈

0

433

2

Windows WSL Vue 설정

2

255

1

Dip, @transactional

0

199

1

[vite] http proxy error: /auth/login

0

1067

2

로그인 하고 나서 GET요청으로 메인페이지 요청

0

246

2

GitHub Collaborator 초대 관련

0

283

2

Window에서 Vue.js 설정

0

334

2

collaboator로 초대받을 수 있을까요??

0

298

2

SecurityMockContext 로부터 유저 정보를 가져오기

0

276

1

섹션9 프론트의 코드를 보고싶습니다,,,

0

427

1

Spring Security - defaultSuccessUrl 질문

0

639

1

강의 화면이 나오지 않습니다. 음성과 자막만 나와요

0

313

1

JPAQueryFactory(em)의 객체 생성자 오류에 대해서 질문이 있습니다ㅜㅜ

0

702

2

ExceptionHandler가 AccessDeniedHandler(Http403Handler)를 먹어버리는 현상

0

1186

2

섹션10 언제 나오나요?

0

489

1

CommentService에서 Repository를 호출하지 않는데도

0

346

1

Editor....를 활용한 패턴에 질문있습니다.

0

500

1

섹션9 vue

0

460

2

Post에 edit 메서드 삼항연산자 질문

0

480

2