728x90
오늘 발생하고 해결한 오류에 대해 작성해보려고 합니다.
Card가 있고 이 Card는 여러개의 Tag를 가질 수 있는 상황입니다.
Card와 Tag는 서로 CardTagMatches라는 중간 테이블에 @OneToMany의 관계로 연관되어 있습니다.
Card와 Tag가 묶여서 복합키로 설정한 모습을 볼 수 있습니다.
Card와 Tag를 복합키로 설정한 이유는 하나의 Card에는 여러가지의 Tag가 들어갈 수 있지만
Tag가 중복해서 들어갈 순 없기때문에 두 개를 묶어 복합키로 만들어 DB에서 불 필요한 검색을 줄여
검색을 조금 더 효율적이게 하기 위해 구현하게 되었습니다.
대충 어떤 관계인지 이해가 되시죠??
위 그림으로 이해하시면 편할 것 같습니다!
Labels라는 Card가 있고 bug, documentation.. 등의 Tag가 있다고 보시면 됩니다!
여러 개의 Card가 있을 수 있구요!
오류는 제가 하나의Card에서 Tag들을 수정해주려고 할 때 발생하였습니다.
첫 에러를 해석해보니
"특정 엔티티가 이미 삭제되었는데, 다른 엔티티가 아직도 이 삭제된 엔티티와 연관을 가지고 있어서 Hibernate가 삭제된 엔티티를 다시 저장하려고 시도할 때 발생한다"는 메시지가 떴습니다.
생각해보니 Card 엔티티 안에 있는 CardTagMatches들을 삭제시켜도
Tag 엔티티에는 Card에서 삭제된 데이터를 참조하고 있는 것 같았습니다.
그래서 Tag와 Card 엔티티를 살펴보았더니
Tag 엔티티
Card 엔티티
이런 식으로 둘다 cascade와 orphanRemoval이 걸려있었습니다.
cascade와 orphanRemoval을 간단하게 설명하자면
cascade는 부모 엔티티에 수행된 작업이 연관된 자식 엔티티로 자동으로 전파되도록 설정하는 데 사용됩니다.
orphanRemoval은 부모 엔티티와 관계가 끊어진 자식 엔티티를 자동으로 삭제하는데 사용합니다.(orphanRemoval = true)
그럼 왜 오류가 생겼는지 느낌이 오지 않나요??
이 오류는 영속성 전이와 관련이 있는데요
영속성 전이는 객체 관계형 매핑에서 하나의 엔티티가 데이터베이서 영속 상태가 될 때,
그 엔티티와 연관된 다른 엔티티들도 자동으로 영속 상태가 되도록 하는 기능을 말합니다.
그럼 이해가 되시죠?
양쪽에서 영속성 전이를 하려고 하니까 오류가 난 것입니다!
그래서 결국 저는 Tag에서 해주는 영속성 전이를 빼주고 첫 번째 오류를 해결하였습니다!
하지만 또 다른 오류가 있었습니다.
저희 프로그램은 태그를 수정할때 Card의 태그를 다 지워주고 다시 설정한 태그를 저장하도록
구현이 되어 있었습니다.
제가 캡쳐를 해놓진 못했는데 하나의 트랜젝션 안에서 키를 삭제하고 다시 키를 저장하였을때
오류가 발생하는 것을 확인하였습니다.
확인해본 결과 하나의 트랜젝션 안에서 데이터들을 조회를 하는 동시에 하나의 키를 삭제하고
다시 똑같은 키를 저장해줄때 오류가 발생하는 것을 확인하였습니다!
그래서 저는
이런 식으로 새로운 태그들을 추가해주며 삭제하는 로직을 구현하여 오류를 해결하였습니다!
하지만 이 부분에도 처음에 contains를 사용하는 부분이 제가 원하는 대로 동작하지 않았습니다.
이유는 contains는 equals로 비교를 하는데
cardTagMatches는 equals로 비교할 수 없는 내용이기
때문에 equals를 커스텀 하여 문제를 해결하였습니다!
이렇게 많은 오류를 해결하여 결국 카드 태그들을 수정하는 것에 성공하였습니다 🎉
좋지 않은 로직일 수도 있고 올바르지 않은 해결법일 수도 있습니다!
다른 좋은 방법 적어주시는 건 언제나 환영입니다!!
'Trouble Shooting' 카테고리의 다른 글
LazyInitializationException 오류 -> 해결 (0) | 2024.07.16 |
---|