트러블슈팅/JPA

[JPA] org.hibernate.PersistentObjectException: detached entity passed to persist 에러 원인 및 해결 방법

Jindory 2022. 11. 15. 07:21
반응형

안녕하세요. 개발자 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 블로그에 방문해주셔서 감사합니다.

[참조]

https://velog.io/@dev-kmson/org.hibernate.PersistentObjectException-detached-entity-passed-to-persist-%EC%97%90%EB%9F%AC

반응형