인프런 커뮤니티 질문&답변

Harper님의 프로필 이미지

작성한 질문수

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

영속성 전이 관련해서 질문드립니다.

해결된 질문

23.01.21 13:15 작성

·

709

·

수정됨

0

 

안녕하세요 강의 수강 후 활용해서 프로젝트를 진행중인데, 영속성 전이 관련해서 질문이 있습니다.

강의 내용처럼 Order에 있는 member에 다음과 같은 설정을 하면

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="member_id")
private Member memberId;

object references an unsaved transient instance - save the transient instance before flushing에러가 발생합니다.

그래서 다음과 같이 영속성 전이 설정을 하면 에러는 안뜨지만 같은 멤버가 두번씩 저장되는 문제가 발생합니다.

@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name="member_id")
private Member memberId;

해당 Order가 Create되면서 Member테이블에 member가 저장되는데 이미 해당 멤버는 db에 저장되어있는 상황. (회원가입하면서 멤버가 저장되어있었음)

ㄴ test05가 두번 저장되어있음

강의 코드는 Order에 영속성 전이 코드를 넣지 않아도 되던데 해당 에러를 발생시키지 않으려면 어떻게 해야할까요?

Member 엔티티와 Order 엔티티 코드 입니다.

@Entity
@Table(name = "ORDERS")
@NoArgsConstructor
@Getter
public class Order {

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   @Column(name = "order_id")
   private Long id;

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name="member_id")
   private Member memberId;

   @Column(name = "post_id")
   private Long postId;

   @Embedded
   private Point price;

   @Column(name="order_at")
   private Timestamp orderAt;

   public static Order of(Member member, Long postId, Point price){
      Order order = new Order();
      order.setMember(member);
      order.postId = postId;
      order.price = price;
      return order;
   }
   public void setMember(Member member){
      this.memberId = member;
      member.getOrders().add(this);
   }
@Entity
@Table(name = "member")
@Getter
@Setter
@NoArgsConstructor
@SQLDelete(sql = "UPDATE member SET deleted_at = NOW() where id = ?")
@Where(clause = "deleted_at is NULL")
public class Member {

   @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;

   @Column(name = "member_id")
   private String memberId;

   private String password;

   @Column(name = "member_name")
   private String memberName;

   private String email;

   @Column(name = "role")
   @Enumerated(EnumType.STRING)
   private MemberRole role = MemberRole.USER;

   @OneToMany(mappedBy = "memberId")
   private List<Order> orders = new ArrayList<Order>();

   public static Member of(String memberId, String password, String memberName, String email){
      Member member = new Member();
      member.setMemberId(memberId);
      member.setPassword(password);
      member.setMemberName(memberName);
      member.setEmail(email);
      return member;
   }

   public static Member of(MemberDto dto){
      Member member = new Member();
      member.setMemberId(dto.getMemberId());
      member.setPassword(dto.getPassword());
      member.setMemberName(dto.getMemberName());
      member.setEmail(dto.getEmail());
      member.setRole(dto.getRole());
      return member;
   }

 

답변 1

1

김영한님의 프로필 이미지
김영한
지식공유자

2023. 01. 22. 19:08

안녕하세요. yooyouny님

트랜잭션 안에서 연관된 Member 엔티티를 찾아온 다음에 해당 Member 엔티티 인스턴스를 연결해주시면 됩니다.

중요한 것은 꼭! 트랜잭션 안에서 연관된 Member 엔티티를 찾아야 합니다.

감사합니다.

Harper님의 프로필 이미지
Harper
질문자

2023. 01. 23. 05:47

감사합니다. dto에서 entity로 전환할때 id를 빼놓고 있었어요.

연결시켜줬었는데 식별자가 다르니 같은 엔티티로 인식하지 못하고 계속 insert 된 것으로 보입니다. 트랜잭션 어노테이션도 추가하였습니다.

덕분에 해결하였습니다 ㅜㅜ 감사합니다~

Harper님의 프로필 이미지

작성한 질문수

질문하기