[Project] JPA/2/연관관계+쿼리

Fortice·2021년 5월 26일
0

Project

목록 보기
4/8

Reference Mapping

정의 규칙

방향

DB에서는 외래키 참조를 하면 외래키 하나로 두 테이블을 조인할 수 있다. 따라서 방향을 나눌 필요가 없으나, 객체는 참조용 필드가 있어야만 다른 객체를 참조할 수 있다.

  • 단방향
    • 두 객체가 있을 때 한 객체만 참조를 가짐
  • 양방향
    • 두 객체가 있을 때 서로 참조를 가짐

불필요한 양방향 설계 시, 객체마다 연관관계가 생겨 객체의 복잡성이 매우 증가한다. 기본적으로 단방향 설계를 하고, 역방향으로 객체 탐색이 필요한 경우(게시물에서 게시판 탐색)에만 양방향으로 추가를 해주는 것이 좋다.

연관 관계의 주인

  • 양방향 관계 시 외래 키를 비롯한 테이블 레코드를 저장, 수정, 삭제 처리의 권한을 갖는 실질적인 관계가 어떤지 JPA에게 알려준다.
    • 외래 키가 있는 곳을 주인으로 한다.
  • 연관 관계의 주인이 아니면 조회만 가능하다.
  • 연관 관계의 주인이 아닌 객체에서 mappedBy속성을 사용해 주인을 지정한다.

게시판-게시물 관계에서 게시판이 게시물을 소유하고 있어 게시판을 주인으로 생각할 수 있지만, 게시판에서 게시물 정보를 바꾸고 싶으면 게시물의 FK를 바꿔 주어야 한다. 따라서 수정이 이루어지는 게시물 객체가 주인이 된다.

다중성

  • N:1 (@ManyToOne)
  • 1:N (@OneToMany)
  • 1:1 (@OneToOne)
  • M:N (@ManyToMany)
    • 실제 DB에서 다대다 관계에서는 Relation Table을 따로 만들어 외래키만 관리하게 된다. JPA에서 자동으로 생성해 준다.
    • Relation Table에 외래키 외에 정보가 들어가거나, 복잡한 쿼리 시 Join에 문제가 없도록, 구현 시 Relation Table을 Entity 클래스로 만들고 1대다+다대1로 풀어서 사용하는 것이 좋을 수 있다.

@ManyToOne, @JoinColumn ...

  • 연관관계 매핑
    • Entity 자신을 기준으로 다중성을 생각해 매핑한다.
    • 각 관계 중 연관관계의 주인이 아닌, 즉 fk를 가지지 않는 Entity의 어노테이션에 mappedBy 속성을 자신의 table 명으로 설정해준다.
      • `@?TO?(mappedBy="table_name")
  • 외래 키 매핑
    • JPA에서는 JDBC를 사용했을 때와 달리 연관 관계에 있는 상대 테이블의 PK를 멤버변수로 갖지 않고, Entity 객체 자체를 참조한다.
    • @JoinColumn 어노테이션의 name 속성에 설정할 FK이름을 설정해 주면 된다.
      • @JoinColumn(name="fk_name")

이제 실제 예시를 보면서 공부한다. 단방향의 경우 연관관계의 주인이 아닌 Entity에 설정을 안해주면 되므로, 양방향만 보기로 한다.

@ManyToOne+@OneToMany / N:1+1:N / 양방향

@Entity
@Table(name="book_store")
@Getter @Setter
public class BookStore {
	@Id
	@Column
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long id;
	
	@Column(nullable=false, length=100)
	private String name;
	
	@OneToMany(mappedBy="book_store")
	private Set<Book> books = new HashSet<Book>();
}

@Entity
@Table( name="book")
@Getter @Setter
public class Book {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	
	@Column(nullable=false, length=200)
	private String title;
	
	@ManyToOne
	@JoinColumn(name ="book_store_id")
	private BookStore bookStore;
}
profile
서버 공부합니다.

0개의 댓글