01-05 16:21:23.215 ERROR 11312 --- [nio-8180-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session : [eci.server.ItemModule.entity.member.MemberRole#eci.server.ItemModule.entity.member.MemberRoleId@f720639e]; nested exception is javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [eci.server.ItemModule.entity.member.MemberRole#eci.server.ItemModule.entity.member.MemberRoleId@f720639e]] with root cause
1번 Member - 6번 Role
이라는 MemberRole
엔티티가 있었는데, 수정 하면서 또 해당 정보가 들어오면서 A different object with the same identifier value was already associated with the session :
라는 이미 동일한 객체가 존재한다고 경고하는 것입니다.멤버 정보 수정 시, 위의 jpa 문을 이용해 member 에 딸린 MemberRole 들을 데려와서, 이들의 Member 을 null로 만들어줌으로써 자동으로 삭제하게 해줄 것입니다.
이것이 가능한 이유는 MemberRole 에서 @OnDelete(action = OnDeleteAction.CASCADE)
를 Member와 맺어줌으로써, Member 와의 연관관계가 사라지면, Member과 외래키 관계를 맺는 MemberRole 이 삭제되도록 설정했기 떄문입니다.
그러나 이런 생각을 가지고 코드를 진행했더니 아래와 같은 에러를 마주했습니다.
org.hibernate.HibernateException: identifier of an instance of eci.server.ItemModule.entity.member.MemberRole was altered from eci.server.ItemModule.entity.member.MemberRoleId@ee814944 to eci.server.ItemModule.entity.member.MemberRoleId@11a00870
위의 에러는 관계형 데이터베이스에서 PK 제약조건의 값은 변경하면 안되며, JPA 또한 이 규칙을 따르기에 PK의 값을 변경하는 행위를 하려 할 때 위와 같은 에러를 뿜는 것입니다.
제 경우에는 member+role 이라는 복합키를 가진 엔티티의 member 을 null 로 변경하면 해당 복합키 엔티티가 삭제될 것이라고 생각했었는데, 그렇게 하면 @Id 어노테이션이 붙은 member 가 null 이 되는 것이므로 복합키의 pk 인 member+role 이 변경되는 것이었습니다.
이 때문에 pk가 변경되면 안된다는 규칙에 따라 위와 같은 에러가 나타났습니다.
결국 구현해야 하는 기능 마감 기한이 바로 이틀 뒤였기에, 어쩔 수 없이 복합키를 유지하면서 해당 오류를 타파할 방법을 찾지 못하여 복합키였던 pk를 자동증가키로 변경함으로써 문제를 해결했습니다.
앞으로 수정, 삭제가 요구되는 다대다 테이블은 함부로 복합키로 선언하지 않고 비교적 느슨하게 수정과 삭제가 가능하도록 자동증가키로 선언해야겠다는 다짐을 하게 되었습니다.