복합키 사용 시 에러 ( org.springframework.dao.DataIntegrityViolationException: A different object with the same identifier value was already associated with the session & identifier of an instance of A was altered from A-ID@ee814944 to A-ID@11a00870

Yunny.Log ·2023년 1월 5일
0

Debugging

목록 보기
59/69
post-thumbnail

1. error

  • 이미 존재하는 복합키 엔티티 pk 와 동일한 pk를 가진 객체가 들어오려고 할 때 발생하는 에러

    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

  • 멤버는 MemberRole을 가지고 있습니다.
  • MemberRole 은 Member 와 Role 의 다대다 관계를 맺어주는 다대다 테이블입니다.
  • 이때 제가 구현하고 싶은 기능은 member 의 정보를 수정하는 것입니다.
    • 멤버 정보 시 positionId(=roleId)로 넘어온 여러개의 역할을 Member와 엮어줌으로써 MemberRole 엔티티를 만들어주고 싶었습니다.

  • 그러나 그때 위의 에러가 발생했던 것입니다.
  • 기존에 1번 Member - 6번 Role 이라는 MemberRole 엔티티가 있었는데, 수정 하면서 또 해당 정보가 들어오면서 A different object with the same identifier value was already associated with the session : 라는 이미 동일한 객체가 존재한다고 경고하는 것입니다.
  • 따라서 덮어쓰기가 안된다는 것을 에러를 통해 확인했으므로, position id 를 보내기 전에 미리 member 에게 존재했던 memberRole 엔티티들을 삭제해 줘야 겠습니다.

  • 멤버 정보 수정 시, 위의 jpa 문을 이용해 member 에 딸린 MemberRole 들을 데려와서, 이들의 Member 을 null로 만들어줌으로써 자동으로 삭제하게 해줄 것입니다.

  • 이것이 가능한 이유는 MemberRole 에서 @OnDelete(action = OnDeleteAction.CASCADE) 를 Member와 맺어줌으로써, Member 와의 연관관계가 사라지면, Member과 외래키 관계를 맺는 MemberRole 이 삭제되도록 설정했기 떄문입니다.

  • 그러나 이런 생각을 가지고 코드를 진행했더니 아래와 같은 에러를 마주했습니다.


2. 복합키의 pk를 변경하려고 할 때 나는 에러

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를 자동증가키로 변경함으로써 문제를 해결했습니다.

  • 앞으로 수정, 삭제가 요구되는 다대다 테이블은 함부로 복합키로 선언하지 않고 비교적 느슨하게 수정과 삭제가 가능하도록 자동증가키로 선언해야겠다는 다짐을 하게 되었습니다.

0개의 댓글