시그마 삽질==six 시그마

JPA -연관관계 매핑 본문

프로그래밍/JPA

JPA -연관관계 매핑

Ethan Matthew Hunt 2020. 4. 8. 22:47

 

우아한 형제들의 김영한 팀장님의  '자바 ORM 표준 JPA 프로그래밍'을

구입하시길 강력 추천드립니다.

책 구입을 원하시는분은 요기를 클릭하시면 됩니다.

저자 직강 인프런 강의도 있습니다 궁금하신분은 요기를 클릭

하단의 내용은 제가 예전에 읽었던 내용을 요약 정리한 것입니다.

 

 

 

 

-키워드

 

객체지향 설계는 각각 객체가 맡은 역할과 책임이 있어서 관련있는 객체끼리 참조하도록 설계해야함

 

차이 관계형 DB 객체
검색 연관객체 검색시 조인사용(외래키사용) 연관객체를 검색시 참조를 사용
방향 무조건 양방향 단방향, (얼추)양방향
양방향 관리 외래키 하나로 두테이블의 연관관계관리 객체참조는 둘, 외래키는 하나기에 두 객체중 하나가 외래키를 관리해야함.so 연관관계의 주인을 정해야함
주인은 FK가 있는 테이블인 엔티티임

 

-객체의 참조와 테이블의 외래키를 매핑

방향: 단방향(두 엔티티중 한쪽만 참조) ,양방향(두 엔티티 서로 참조) /양방향의 장점은 반대방향으로 객체 그래프 탐색기능이 추가

다중성: 다:1, 1:다,1:1,다:다

연관관계 주인: 객체를 양방향 연관관계로 만들면 연관관계 주인을 정해야함

 

 

글이 하나 있고 댓글이 여러개 있는경우를 가정해보자.

 

@Entity
public class Reply{

@Id
@Column(name=REPLY_ID)
private Long id;


//연관관계 매핑
@ManyToOne
@JoinColumn(name="BOARD_ID") //FK명
private Board board;

.....

}

name: 매핑할 외래키 이름

referencedColumeName: 외래키가 참조하는 대상테이블의 컬럼명(기본값은 참조하는 테이블의 기본키 컬럼명)

 

@Entity
public class Board{

@Id
@Column(name=BOARD_ID)
private Long id;

@OneToMany(mappedBy="board")
private List<Reply> replies= new ArrayList<Reply>();

.....

}

저 위 mappedBy의 board는 Reply 엔티티의 board 필드임(반대쪽 매핑의 필드의 이름값)

 

-연관관계 조회

1. 객체 그래프 탐색(객체 연관관계를 사용한 조회)

2. 객체 지향 쿼리 사용(JPQL)

 

 

-연관관계 제거

연관관계 setXX(null) 설정 

 

 

-연관된 엔티티삭제

연관된 엔티티삭제하려면 기존의 연관관계를 먼저 제거하고 삭제해야함.

 

-양방향 매핑 규칙

연관관계 주인만이 외래키를 관리(CUD)할 수 있고 주인아닌쪽은 R만 가능

주인은 mappedBy 속성을 사용하지 않음

주인은 FK가 있는 테이블인 엔티티임!

관계DB에서는 '다' 쪽이 외래키를 가짐. 고로 @ManyToOne이 항상 주인. mappedBy 설정불가

 

 

-양방향 연관관계 주의점

 

주인이 아닌곳에만 값 입력하고 주인은 값입력 안하는 실수

객체 관점에서 양쪽 방향 모두 값을 입력해주는 것이 안전함

객체의 양방향 연관관계는 양쪽 모두 관계를 맺어줘야함

toString() 이나 Lombok 사용시 무한루프에 빠지지 않게 주의해야함!!!

(ToStringBuilder클래스활용, 각각@ToString(exclude = "참조변수"))

 

 

-연관관계 편의 메소드

 

한번에 양방향 관계를 설정하는 메소드임. 한쪽 엔티티의 set으로 양방향 관계를 설정가능

@Entity
public class Reply{
...
@ManyToOne
@JoinColumn(name="BOARD_ID")
private Board board;

public setBoard(Board board){
  this.board=board;
  board.getReplies().add(this);
 }

....

}

 

 

-변경전-

Board board1 = new Board("t1", "보드타이틀");

em.persist(board1 );

 

Reply reply1= new Reply("s1","댓글타이틀");

reply1.setBoard(board1);

board1.getReplies().add(reply1);  <--변경 후 삭제가능

em.persist(reply1);

 

Reply reply2= new Reply("s2","댓글타이틀");

reply2.setBoard(board1);

board2.getReplies().add(reply2); <--변경 후 삭제가능

em.persist(reply2);

 

 

 

-변경후-

 

Board board1 = new Board("t1", "보드타이틀"); //p생성

em.persist(board1 );

 

Reply reply1= new Reply("s1","댓글타이틀1");  //c생성 , p insert

reply1.setBoard(board1);

em.persist(reply1);

 

Reply reply2= new Reply("s2","댓글타이틀2");

reply2.setBoard(board1);

em.persist(reply2);

 

 

 

-연관관계 편의 메소드 작성 시 주의사항

 

연관관계의 변경이 있을시 선생1:학생 다 상황에서 예를들어 만약 학생1이 선생님1이 싫어서 선생님2로 변경한다면..

 

student1.setTeacher(teacher1);

student1.setTeacher(teacher2);

 

List<Student > students=teacher1.getStudents(); // 선생님1의 학생에 s1이 여전히 조회된다.

 

고로 기존 학생이 있으면 기존 학생과 선생님간의 연관관계 삭제하는 코드를 작성해야함.

@Entity
public class Student{
...
@ManyToOne
@JoinColumn(name="teacher_id")
private Teacher teacher;

public setTeacher(Teacher teacher){
  //기존 학생과의 관계를 제거
  if(this.teacher !=null){
   this.teacher.getStudents().remove(this);
  }
  this.teacher=teacher;
  teacher.getStudents().add(this);
 }

....

}

 

'프로그래밍 > JPA' 카테고리의 다른 글

JPA -고급 매핑  (0) 2020.04.09
JPA -다양한 연관관계 매핑  (0) 2020.04.09
JPA -Entity Mapping  (0) 2020.04.08
JPA -Persistence Management  (0) 2020.04.08
JPA-Flow  (0) 2020.04.08
Comments