[TIL] JPA계의 포인터 (@OneToOne, @OneToMany)

wannabeing·2025년 5월 1일
2

SPARTA-TIL

목록 보기
17/22
post-thumbnail

@OneToMany

  • One이 연관관계의 주인이다.
  • 테이블 일대다 관계에서는 다(N)쪽에 외래키가 있다.
  • Team(1) : Member(N) 으로 예시를 들어보자.

Team(1)에서 @OneToMany로 연관관계 단방향 매핑을 해보자!

@Entity
@NoArgsConstructor
public class Tean {

    @Id @GenratedValue
    @Column(name ="team_id")
    private Long id;
    
    ...
    
    @OneToMany
	@JoinColumn(name = "team_id")
	private List<Memeber> members = new ArrayList<>();
   
    ...
}
  • @JoinColumn을 반드시 사용해야 한다.
    @JoinClumn의 name속성값은 나의 PK 컬럼명을 입력한다.
    @JoinClumn을 안쓰면 중간테이블이 생겨버린다!

❓ 만약 멤버를 추가한다면?

Member member = new Member();
member.setName("hazard");

entityManager.persist(member); // 영속상태 및 Insert 쿼리 날림

Team team = new Team();
team.setName("chelsea");
team.getMembers().add(member); // ✅

entityManager.persist(team); // 영속상태 및 Insert 쿼리 날림
  1. Member Insert 쿼리문 실행
  2. Team Insert 쿼리문 실행
  3. Member Update 쿼리문 실행 ✅

현재는 쿼리가 적어서 상관없지만, 테이블관계가 복잡해지고 쿼리가 복잡해질 경우에
나는 Team을 건드렸는데, Member 업데이트문을 보게 된다.
코드를 이해하고 디버깅하는데 많은 비용이 소요되게 된다.

따라서 다대일 단방향 관계를 갖고 있다가, 필요시에 양방향관계를 설정하는 방법을 추천한다.


@OneToOne

파일과 썸네일의 관계를 1:1로 가정해보겠다.

1. 파일과 썸네일의 단방향 일대일 매핑 (파일엔티티가 주인)

public class File {
	@Id
    @Column(name ="file_id")
    private Long id;
    
    @OneToOne
    @JoinColumn(name ="thumb_id")
    private Thumbnail thumbnail;
    
    ...
}
public class Thumbail {
	@Id
    @Column(name ="thumb_id")
    private Long id;
    
    ...
}

2. 파일과 썸네일의 양방향 일대일 매핑

public class File {
	@Id
    @Column(name ="file_id")
    private Long id;
    
    @OneToOne
    @JoinColumn(name ="thumb_id") // 외래키 컬럼명 지정
    private Thumbnail thumbnail;
    
    ...
}
public class Thumbail {
	@Id
    @Column(name ="thumb_id")
    private Long id;
    
    @OneToOne(mappedBy ="thumbnail") // 읽기 전용
    private File file;
    
    ...
}

3. 만약 Thumbnail 테이블에 FK가 있으면, File 테이블에서 관리 가능한가요?

  • 불가능합니다!
  • JPA에서 지원해주지 않는다.
  • @OneToMany 단방향처럼 한다는 말인데, 불가능함!

✅ OneToOne 정리

  • 주인 테이블에 외래키(FK)
    • 객체 지향적
    • JPA 매핑 시 편리하다
    • 주인 테이블만 조회해도 대상테이블에 데이터가 있는지 확인 가능
    • 값이 없다면 외래키에 null이 들어가게 됨
  • 대상 테이블에 외래키(FK)
    • 양방향 매핑이 필연적
    • 단방향은 지원하지 않음
    • 추후에 일대다(@OneToMany)로 변경 시에 편리함

💡 @OneToOne 양방향 연관관계에서 외래키(FK)가 주인이 아닌 엔티티에 있을 경우, 지연 로딩으로 설정해도 즉시 로딩이 된다.

public class File {
	@Id
    @Column(name ="file_id")
    private Long id;

    @OneToOne(fetch = FetchType.LAZY) // ✅ 지연로딩 설정
    @JoinColumn(name ="thumb_id") // 외래키 컬럼명 지정
    private Thumbnail thumbnail;

    ...
}
public class Thumbail {
	@Id
    @Column(name ="thumb_id")
    private Long id;

    @OneToOne(mappedBy ="thumbnail") // 외래키 컬럼명 지정
    private File file;

    ...
}
  • 지연로딩으로 설정하면, File 객체 안에 있는 Thumbnail 객체프록시 객체로 JPA가 설정한다.
  • 하지만 외래키가 Thumbnail 테이블(대상)에 있으므로,
    File 테이블(주인)을 조회해도 반드시 Thumbnail 테이블 조회를 해야되므로 즉시로딩된다.

@ManyToMany

직접적으로는 잘 안쓰고 다른 방법으로 대체하는게 좋다고 한다.
연결테이블을 추가하여 다대일 관계로 풀어내는게 좋다.

profile
wannabe---ing

2개의 댓글

comment-user-thumbnail
2025년 5월 1일

항상 느끼는건데 글 내용도 좋지만 짤이 완벽한 것 같습니다

1개의 답글