[JPA] org.hibernate.PersistentObjectException: detached entity passed to persist 에러 원인 및 해결 방법
안녕하세요. 개발자 Jindory입니다.
오늘은 JPA Test 코드 작성중 PersistentObjectException가 발생했을때 원인 및 해결방법에 대해서 작성해보고자 합니다. 본 글은 dev-kmson.log 님의 글을 참고해서 작성하였습니다.
# 글 작성 이유
Test Code를 작성하고 Junit을 돌리는 과정에서 PersistentObjectException을 직면했으며, 해당 에러가 왜 발생하는지 어떻게 에러를 잡을 수 있는지 숙지하여 다음에는 이와 같은 에러를 만나지 않도록 테스트 코드를 작성하고 발생시 빠르게 코드수정을 하기 위하여 작성하였습니다.
# 에러 발생 및 상황 설명
TeamEntity를 생성하고 원하는 Id로 초기화 한 후 save하는 과정에서 아래와 같은 에러가 발생했습니다.
# 원인
엔티티 클래스에 @Id를 부여한 필드에 @GeneratedValue를 작성하여 AUTO, SEQUENCE, IDENTITY 전략 등 데이터베이스에게 key 값을 자동 생성하도록 하는 전략을 선택했다면, 엔티티 객체 생성시 Id에 해당하는 필드에 직접 값을 입력하면 안 됩니다.
(Service Layer Mock 코드 작성시 원하는 Id를 생성하기 위해 인위적으로 부여했다가, 실제 Method를 사용하는 Repository Layer 테스트 코드에서 Id 값을 바뀌면서 해당 문제가 발생)
@Entity
@Table(name="TEAM")
@NoArgsConstructor
public class TeamEntity extends BaseEntity{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="TEAM_ID")
public Long id;
/* 중략 */
public void initId(Long id) {
if(this.id == null) {
this.id = id;
}
}
}
원인 발생 코드
@Test
@DisplayName("Team이 요청한 join 조회")
public void findTeamJoinApplication() {
TeamEntity rteam = new TeamEntity("RedTeam","Seoul",BelongType.CLUB,"I'm a red team if you like red, will you join us?");
TeamEntity oteam = new TeamEntity("OrangedTeam","Seoul",BelongType.CLUB,"I'm a orange team if you like red, will you join us?");
TeamEntity yteam = new TeamEntity("YellowTeam","Seoul",BelongType.CLUB,"I'm a yellow team if you like red, will you join us?");
TeamEntity gteam = new TeamEntity("GreenTeam","Seoul",BelongType.CLUB,"I'm a green team if you like red, will you join us?");
TeamEntity bteam = new TeamEntity("BlueTeam","Seoul",BelongType.CLUB,"I'm a blue team if you like red, will you join us?");
TeamEntity iteam = new TeamEntity("IndigoTeam","Seoul",BelongType.CLUB,"I'm a indigo team if you like red, will you join us?");
TeamEntity pteam = new TeamEntity("PuppleTeam","Seoul",BelongType.CLUB,"I'm a purple team if you like red, will you join us?");
// 데이터베이스에 키 생성 전략을 취했으므로 엔티티를 생성하면서 key 값을 인위적으로 부여하면 안 됨
rteam.initId(10L);
oteam.initId(10L);
yteam.initId(10L);
gteam.initId(10L);
bteam.initId(10L);
iteam.initId(10L);
pteam.initId(10L);
teamRepository.save(rteam);
teamRepository.save(oteam);
teamRepository.save(yteam);
teamRepository.save(gteam);
teamRepository.save(bteam);
teamRepository.save(iteam);
teamRepository.save(pteam);
}
# 해결방법
Id값을 셋팅하는 코드를 제거후 다시 테스트를 돌리니 해당 문제는 해결되었습니다.
이렇게 JPA Test 코드 작성중 PersistentObjectException가 발생했을때 원인 및 해결방법에 대해서 알아봤습니다.
혹시라도 정정할 내용이나 추가적으로 필요하신 정보가 있다면 댓글 남겨주시면 감사하겠습니다.
오늘도 Jindory 블로그에 방문해주셔서 감사합니다.
[참조]