2021-12-14 02:11:25.930 ERROR 27768 --- [http-nio-8002-exec-2] c.p.m.c.e.GlobalExceptionHandler : handleException
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)
2:12
Caused by: javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:81)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:104)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562)
... 102 common frames omitted
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because "current" is null
at org.hibernate.type.IntegerType.next(IntegerType.java:70)
at org.hibernate.type.IntegerType.next(IntegerType.java:22)
at org.hibernate.engine.internal.Versioning.increment(Versioning.java:92)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.getNextVersion(DefaultFlushEntityEventListener.java:428)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.scheduleUpdate(DefaultFlushEntityEventListener.java:305)
at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:171)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:229)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:93)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1416)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:507)
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3299)
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2434)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:449)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281)
at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101)
... 103 common frames omitted
문제 원인 : User는 version 필드로 관리됨.
하지만 기존에 있던 User에 대해 version이 null 값이였다.
문제 해결 : version 값 null → 0
<aside> 📢 MonthSub
</aside>
우리 서비스에서는 READ COMMITTED + 낙관적락을 사용할 것이다.
비관적락을 쓸 이유는 아직 없다고 생각하여 추후 낙관적락으로 처리 불가능할 경우 비관적으로 바꿀 예정이다.
EX) 브라우저에서 동시에 10번에 결제가 들어온다고 해보자.
낙관적락을 쓰는 이유 : 락을 걸지 않으면 동시에 10번 결제가 들어오면 10번 결제로 처리되지만
User에 포인트는 한번만 깎이게 된다. 악의적으로 사용하면 포인트만 한번에 깎이고 여러개의 시리즈를 볼 수 있는 것이다.
낙관적락
최초 한번의 커밋만 인정된다 ( 한번 결제 완료 )
나머지 9번에 대해서는 예외로 잡고 포인트를 깎아주는 플로우이다.