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번에 대해서는 예외로 잡고 포인트를 깎아주는 플로우이다.