[Spring] Could not commit JPA transaction
문제 상황
OAuth를 통한 로그인 테스트 중 발생했다. 로그인 ID를 이메일로 설정했는데 OAuth로 처음 로그인하는 경우 회원가입까지 자동으로
되도록 만들었는데 그 과정에서 메인 페이지로 넘어가지 않고 다음 에러 로그를 남겼다.
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction
Caused by: jakarta.persistence.RollbackException: Error while committing the transaction
at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:65) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:561) ~[spring-orm-6.0.10.jar:6.0.10]
... 98 common frames omitted
Caused by: jakarta.validation.ConstraintViolationException: Validation failed for classes [yeolJyeongKong.mall.domain.entity.User] during persist time for groups [jakarta.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='길이가 0에서 10 사이여야 합니다', propertyPath=username, rootBeanClass=class yeolJyeongKong.mall.domain.entity.User, messageTemplate='{org.hibernate.validator.constraints.Length.message}'}
ConstraintViolationImpl{interpolatedMessage='길이가 8에서 15 사이여야 합니다', propertyPath=password, rootBeanClass=class yeolJyeongKong.mall.domain.entity.User, messageTemplate='{org.hibernate.validator.constraints.Length.message}'}
]
at org.hibernate.boot.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:151) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.boot.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:81) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:215) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:98) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:606) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:358) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2301) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1966) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-6.2.5.Final.jar:6.2.5.Final]
... 99 common frames omitted
해결 방법
로그를 보면 각 필드에 대해 validation 체크가 이뤄지는 도중 발생한 오류였는지 길이가 0에서 10 사이여야 합니다
라는 메시지
가 남겨져 있다. 따로 이런 에러 메시지가 남도록 설정한 적이 없었기 때문에 각 필드에 제약조건으로 설정했던 애노테이션에 설정된
메시지라고 생각했고, 길이가 0~10, 8~15로 설정된 필드가 있는지 찾아보니 username
과 password
가 있었다.
public class User {
...
@NonNull @Length(max = 10)
private String username;
@NonNull @Length(min = 8, max = 15)
private String password;
...
public User(String email, String password, String provider, String providerId) {
username = email;
this.email = email;
this.password = password;
...
}
}
username
은 email
을 그대로 사용하고, password
는 OAuth에서 따로 지정하지 않기 때문에 랜덤값을 받고 있었는데 모두
모두 최대 길이 제한을 넘어서 발생하는 문제였다. 그리고 password
는 BCryptPasswordEncoder
로 인코딩을 거친 값이 넘어
오고 있었기 때문에 길이 제한을 쉽게 넘었다. 그래서 username
은 @
앞에 적힌 ID만 받도록 하고 최대 길이 제한을 늘리고
password
는 제한을 없앤 뒤 값을 저장하지 않도록 처리했다.
public class User {
...
@NonNull @Length(max = 20)
private String username;
@NonNull
private String password;
...
public User(String email, String provider, String providerId) {
username = email.substring(0, email.indexOf('@'));
this.email = email;
...
}
}
댓글남기기