Open berryberrybin opened 1 year ago
데이터베이스 구조
@ManyToOne
만 추가해줬음
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE") private String title;
@ManyToOne @JoinColumn(name = "BOARD_ID") private Board board; //... getter, setter }
@Entity public class Board { @Id @GeneratedValue private Long id; private String title; //... getter, setter }
### N:1 다대일 양방향
- 코드
- 양방향 만들기 위해선 (1)쪽에 `@OneToMany` 추가
- 양방향 매핑 사용시 연관관계 주인을 `mappedBy`로 지정
- Posts(N) : Board(1)에서 **Post가 PK를 가지고, 주인역할을 함**
```java
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
@ManyToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
//... getter, setter
}
@Entity
public class Board {
@Id @GeneratedValue
private Long id;
private String title;
@OneToMany(mappedBy = "board") // posts 테이블에 있는 board 필드에 의해 매핑되었다는 의미
List<Post> posts = new ArrayList<>();
//... getter, setter
}
@OneToMany 이용, @JoinColumn을 이용해 조인함
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE")
private String title;
//... getter, setter
}
@Entity public class Board { @Id @GeneratedValue private Long id; private String title;
@OneToMany
@JoinColumn(name = "POST_ID") //일대다 단방향을 @JoinColumn필수
List<Post> posts = new ArrayList<>();
//... getter, setter
}
- 문제점
- post 저장시에는 insert 쿼리 잘 나가지만 board 저장시에 Board insert 쿼리 나간 후 post를 update하는 쿼리가 나감
- `board.getPosts().add(post);` 부분에서 Board 엔티티는 Board 테이블에 매핑되기때문에 Board 테이블에 직접 지정할 수 있지만, Post 테이블의 FK(Board_ID)를 저장할 방법이 없으므로, 조인 및 업데이트 쿼리를 날려야 함
- 즉, Board만 수정했는데 다른 수정이 생겨 쿼리가 발생함
- 1:N 단방향 연관관계 매핑이 필요한 경우에는 ❗차라리 N:1 양방향 연관관계 매핑이 유지보수가 더 쉬움 ❗
```java
//...
Post post = new Post();
post.setTitle("가입인사");
entityManager.persist(post); // post 저장
Board board = new Board();
board.setTitle("자유게시판");
board.getPosts().add(post);
entityManager.persist(board); // board 저장
//...
게시글(Post)에 첨부파일(Attach)을 반드시 1개만 첨부할 수 있다고 가정
@Entity
public class Post {
@Id @GeneratedValue
@Column(name = "POST_ID")
private Long id;
@Column(name = "TITLE") private String title;
@OneToOne @JoinColumn(name = "ATTACH_ID") private Attach attach; //... getter,setter } @Entity public class Attach { @Id @GeneratedValue @Column(name = "ATTACH_ID") private Long id; private String name; //... getter, setter }
@OneToOne 설정하고, mappedBy 설정만 해서 읽기 전용으로 만들어 주면 양방향이 됨
외래키를 어디서 관리하는 것이 좋은가?
게시글이 여러 개의 첨부파일을 첨부할 수 있도록 비즈니스가 변경될 경우, 다(N)쪽인 Attach테이블에 외래 키가 있는 것이 변경에 유연함
But, 다(N)이 될 확률이 높은 테이블에 외래키를 놓은 것이 무조건 좋지는 않음
객체 입장에서 Post쪽(1)에서 외래 키를 갖게되면, Post를 조회할 때마다 이미 Attach의 참조를 갖고 있기 때문에 성능상 이득이 있음
즉, 1:1이라고 신중히 정했다면, 주테이블(Post)에 외래키를 두는 것이 좋음
@Entity
public class Attach {
@Id @GeneratedValue
@Column(name = "ATTACH_ID")
private Long id;
private String name;
@OneToOne(mappedBy = "attach") private Post post; //... getter, setter }
단방향 VS 양방향
데이터베이스 테이블은 외래키 하나로 양 쪽 테이블 조인이 가능하여 단방향과 양방향을 나눌 필요 없음
But, 객체는 참조용 필드가 있는 객체만 다른 객체를 참조하는 것이 가능함
비지니스 로직에서 두 객체가 참조 필요 여부를 고민
무조건 양방향 관계를 하는 것이 좋은가?
연관관계 주인