연관관계 매핑

2024. 10. 15. 08:41·트러블슈팅

프로젝트를 하던도중 편의 메소드를 사용해야하는 상황이 생겼다. 이런 저런 시도를 해보았지만(나의 이해도부족)결국 성공하지 못하고 repository를 하나 더 만들어서 해결했다.(나중에는 편의메소드를 사용했지만)

삽질

  • One
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class One {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;

  @OneToMany(mappedBy = "one")
  private List<Many> manyList;

  public One(String name) {
    this.name = name;
  }
}
  • Many
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
public class Many {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  @ManyToOne(fetch = FetchType.LAZY)
  private One one;
  private String name;
}
  1. 편의 메서드 사용
public class One {

    ...

    public void addMany(Many many) {
      manyList.add(many);
      many.setOne(this);
    }
}
public class Many {

    ...

    public void setOne(One one) {
      this.one = one;
    }
}
public class OneRequest {

    ...

    public One toOne() {
      One one = new One(id, name);
      for (ManyRequest request : manyList) {
        one.addMany(request.toMany());
      }
      return one;
    }
}
public class ManyRequest {

    ...

    public Many toMany() {
      return new Many(id, name);
    }
}

이렇게 설정하고 request를 보내보면... 분명히 양쪽다 넣어줬는데 `One`만 저장된다

  1. 영속성 전이
    나머지 코드는 다 똑같고
public class One{ 
        ... 
        @OneToMany(mappedBy = "one", cascade = CascadeType.PERSIST) 
        private List<Many> manyList = new ArrayList<>(); 
        ... 
}

딱 이 부분만 다르게 했다.

그리고 request를 보내봣더니 저장이 잘 된다.

문제 원인

  • 데이터 베이스의 cascade와 헷갈렸다

SimpleJpaRepository파일을 열어보면

JPA에서는 이런식으로 save를 할때 엔티티를 영속화 시켜주는데 이 과정에서 cascade가 없으면 자식 엔티티까지 영속화 하지 못한다. 그래서 저장이 안된것다..ㅜㅜ

편의 메소드 최적화

양방향 연관관계는 양 쪽 객체를 모두 신경써야 하는데, 하나의 메소드에서 양측에 관계를 설정하게 해주는 것이 안전하다. 이렇게 한번에 양방향 관계를 설정하는 메소드를 연관관계 편의 메소드라고 한다.

  • 다대일측(User)에서 연관관계를 지정할 때 기존 연관관계는 끊어주어야 하고(one1 → one2 로 바꿀때 one1에 계속 남아있을 수 있다.), 무한 루프를 방지 해야한다.
public class One {

    ...

    public void addMany(Many many) {
      manyList.add(many);
      if (many.getOne() != this) {
        many.setOne(this);
      }
    }
}
public class Many {

    ...

    public void setOne(One one) {
      if (this.one != null) {
        this.one.getManyList().remove(this);// 기존 연관관계 제거
      }
      this.one = one;
      if (!one.getManyList().contains(this)) {// 무한루프 방지
        one.addMany(this);
      }
    }
}

'트러블슈팅' 카테고리의 다른 글

연관관계 컬랙션 타입 관리  (1) 2024.10.15
Spring Batch processor 이야기  (0) 2024.10.15
어노테이션 기반 권한 관리  (0) 2024.10.14
관제값 조회 디자인 패턴 적용  (1) 2024.10.13
그래프 조회 속도 개선  (1) 2024.10.13
'트러블슈팅' 카테고리의 다른 글
  • 연관관계 컬랙션 타입 관리
  • Spring Batch processor 이야기
  • 어노테이션 기반 권한 관리
  • 관제값 조회 디자인 패턴 적용
jamin
jamin
  • jamin
    jamin
    jamin
  • 전체
    오늘
    어제
    • 전체 (83)
      • 트러블슈팅 (31)
      • 개념 저장소 (19)
        • coroutine (10)
        • spring reactive (9)
        • network (0)
      • 코딩 테스트 (32)
  • 태그

    누적합
    instancio
    분리집합
    다익스트라
    dfs
    코테
    백준
    JPA
    코딩테스트
    그리디
    경로압축
    batch
    Kotlin
    정렬
    대용량 데이터
    spring reactive
    log
    coroutine
    cluster mode
    백준 23758
    mirroring mode
    reactive
    sinks
    error alram
    그리디 알고리즘
    BFS
    수학
    spring boot
    DP
    다이나믹 프로그래밍
  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
jamin
연관관계 매핑
상단으로

티스토리툴바