[Error] TransientPropertyValueException에러..
개발은 에러의 무한반복.. 에러라는 쳇바퀴를 돌리는 한 마리의 헴스터..
프로젝트를 진행하던 중에 에러를 만났다.
TransientPropertyValueException에러였는데 하이버네티스에서 나온 에러이다.
에러의 원인은 두 엔티티를 매핑시키고 데이터를 넣는 중에 영속성 컨텍스트에 들어가지 않은 객체를 연관관계 주인에 넣을려고 해서 발생한 에러였다.
말로하면 너무 어려우니 코드를 살펴보자.
Image image = new Image();
Member member = new Member();
member.setImage(image);
memberRepository.save(member);
에러부분에만 집중하기 위해서 아주 간단하게 표현했다. 이미지는 프로필이미지 하나만 저장하기 때문에 1:1의 관계이고 여기서 연관관계의 주인은 Member이다.
아직 JPA에 익숙하지 않은 사람들은 이상한점을 모를수도 있겠다. 필자가 그랬으니..
Member에 Image를 넣기위해서는 Image가 생성이 되어야 하는데 사실 지금의 상태는 아직 생성된 상태가 아니다. Image는 JPA의 어떠한 관리도 받지않고 있기 때문이다. 이렇게 동작시키면 Member객체에 Image의 FK가 생성될수가 없다.
해결방법은 Image도 JPA의 관리를 받도록 해주어여한다.
Image image = new Image();
imageRepository.save(image); // 추가
Member member = new Member();
member.setImage(image);
memberRepository.save(member);
이렇게 Image도 영속성 컨텍스트에 입력시키야 Image객체가 바르게 생성이 된 상태이다.
그런데 Image를 따로 사용하는 경우가 있다면 괜찮을지 모르겠지만 만약 member를 통해서만 이미지를 조회하는 경우라면 오히려 코드의 낭비가 될 수도 있다고 생각한다. Image를 따로 다루지 않는다면 ImageRespository도 꼭 필요하지는 않을 것이다.
이런 경우 부모객체인 member를 중심으로 코드를 짜되 자식객체인 image가 따라올 수 있게 하기 위해서 cascade를 이용할 수 있다.
cascade는 부모객체에 따라서 자식객체가 동작할 수 있도록 설정해주는 작업이다.
member객체에 코드를 추가해보자
@Entity
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "member_id")
private Long id;
@OneToOne(cascade = CascadeType.ALL) // 이 부분이 포인트
@JoinColumn(name = "image_id")
private Image image;
}
CascadeType.ALL 으로 설정하면 persist, remove, merge 등 다양한 종류의 설정을 모두 적용하겠다는 의미이다.
이렇게 설정한 후 다시 처음의 코드를 실행해보자
Image image = new Image();
Member member = new Member();
member.setImage(image);
memberRepository.save(member);
이제는 image를 따로 persist하지 않아도 잘 저장된다.
어찌보면 너무나도 당연한 문제지만 JPA를 배워가는 입장에서는 신경쓰지 않으면 실수할 수도 있는 부분인 것 같다.
'에러모음' 카테고리의 다른 글
JPA필수코스 N+1문제 해결하기 (0) | 2022.06.25 |
---|---|
스프링부트 gradle build 실패 (0) | 2022.06.15 |
[Error] Mockito를 사용한 단위테스트(form데이터 전송) (0) | 2022.05.17 |
[Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회 (0) | 2022.05.03 |
[Error] Form태그 안에 버튼이 있다면 버튼의 역할은? (0) | 2022.04.21 |
댓글
이 글 공유하기
다른 글
-
스프링부트 gradle build 실패
스프링부트 gradle build 실패
2022.06.15 -
[Error] Mockito를 사용한 단위테스트(form데이터 전송)
[Error] Mockito를 사용한 단위테스트(form데이터 전송)
2022.05.17 -
[Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회
[Error] JPQL에서 엔티티조인 후 내부의 엔티티 조회
2022.05.03 -
[Error] Form태그 안에 버튼이 있다면 버튼의 역할은?
[Error] Form태그 안에 버튼이 있다면 버튼의 역할은?
2022.04.21