-
JPA (5) - 연관 관계 매핑 (다대일,일대다,일대일,다대다)카테고리 없음 2024. 1. 11. 14:45
-> 관계를 왼쪽 테이블 기준으로 볼 것이다.
1. 다대일
1.1 다대일 단방향
출처: JPA기본편(김영한) -인프런 - 가장 많이 사용하는 연관관계
- 다대일의 반대가 일대다
1.2 다대일 양방향
출처: JPA기본편(김영한) -인프런 - 외래키가 있는 쪽이 연관관계의 주인
- 양쪽을 서로 참조하도록 개발
- 먼저 다대일 단방향을 했다가, 필요에 의해 양방향 전환 고려
2. 일대다
2.1 일대다 단방향
출처: JPA기본편(김영한) -인프런 @Entity public class Team{ @Id @GeneratedValue private Long id; private String name; @OneToMany @JoinColumn(name ="TEAM_ID") List<Member> members = new ArrayList<>(); }
- 일이 연관관계의 주인이다. (JoinColumn이 member한테 먹음)
- 객체와 테이블의 차이로, 반대편 테이블의 외래키를 관리하는 구조 (운영상 매우 구리다. 차라리 다대일 양방향하자)
- JoinColumn을 사용하지않으면, JoinTable라는 매핑 테이블을 생성한다. (joinColumn 꼭 사용하자)
- 연관관계 관리를 위해 UPDATE SQL이 추가로 실행 될 수 있다.
*JoinColumn에 다른 값 (pk외) 주고싶으면 엔티티를 Seializable한 뒤에, @JoinColumn에 옵션을 이용하자
2.2 일대다 양방향
출처: JPA기본편(김영한) -인프런 - 공식적으로 존재하지 않는 매핑이다.
- @JoinColumn(insertable=false,updatable=false)사용해서 억지로 넣은 것
- 그냥 다대일 양방향 써라..
@Entity public class Team{ @Id @GeneratedValue private Long id; private String name; @OneToMany @JoinColumn(name ="TEAM_ID") List<Member> members = new ArrayList<>(); } @Entity public class Member{ @Id @GeneratedValue private Long id; private String name; @ManyToOne @JoinColumn(name ="TEAM_ID",insertable=false,updatable=false) private Team team; }
3. 일대일
- 일대일은 주 테이블이나 대상 테이블 중에 외래 키 선택 가능하다
- 외래 키에 DB에 유니크 제약조건 추가하자
3.1 일대일 단방향
출처: JPA기본편(김영한) -인프런 - 1대1 연관관계라 테이블에 FK가 중복 저장되면 안됨! (그렇게된다면, 다대일이다)
public class Member { @Id @Column(name = "MEMBER_ID") private Long id; @OneToOne @JoinColumn(name = "LOCKER_ID") private Locker locker; @Column(name = "USERNAME") private String username; }
3.2 일대일 - 양방향
public class Member { @Id @Column(name = "MEMBER_ID") private Long id; @OneToOne @JoinColumn(name = "LOCKER_ID") private Locker locker; @Column(name = "USERNAME") private String username; } public class Locker { @Id private Long id; @OneToOne(mappedBy="locker") private Member member; }
- 다대일과 유사
*대상테이블 (Locker 등)에서 단뱡향으로 연관관계 맺는 것 현재로는 불가능함! (Locker가 Member를 관리하는건 이상)
애초에 Locker에 Member가 없는데 어케 관리해...
출처: JPA기본편(김영한) -인프런 *양방향은 그냥 뒤집은것 헷갈리니까 주테이블 대상테이블 잘 설정해서 주테이블 방향으로 가자
*대상테이블에 fk두고 사용할 것이라면 양방향으로 만들어야한다.
> 대상테이블에 fk를 두고 사용하면 편한점은 추후에 일대다 관계로 변경시 테이블 구조가 유지된다!
> 단점은 프록시 기능의 한계로 지연로딩으로 설정해도 항상 즉시 로딩됨 (주테이블 조회시 반드시 대상테이블 조회 -> 대상 테이블 fk값을 통해 주테이블을 불러오는 방식이라 그러하다!)
4. 다대다
- 관계형 데이터 베이스는 테이블 2개로 다대다 관계 표현불가
- 연결 테이블 추가해서 일대다 - 다대일 관계로 풀어야한다.
(부모1 -자식1,2,3 일대다(다대일) -> 부모1 자식1,2,3 , 부모 2 자식1,2,3 (다대다))
출처: JPA기본편(김영한) -인프런 - 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계 가능하다.
- @ManyToMany사용하고 @JoinTable을 사용하자
- 단방향 양방향 둘다 가능하다.
-편리해보이지만 실무에서 사용하지 않는다. -> 연결테이블이 단순히 연결만 하고 끝나지 않는다. (다른 데이터 들어올 수 있음)
- 연결 테이블용 엔티티를 추가해서 OneToMany, ManyToOne으로 풀어내자
출처: JPA기본편(김영한) -인프런 //카테고리 @ManyToMany @JoinTable(name = "CATEGORY_ITEM",joinColumns = @JoinColumn(name = "CATEGORY_ID"),//내가 들어갈 컬럼 inverseJoinColumns = @JoinColumn(name = "ITEM_ID") //중간테이블에서 내가 조인할 컬럼, 상대 컬럼 지정 ) private List<Item> items = new ArrayList<>(); //item 엔티티 @ManyToMany(mappedBy = "items") //어차피 값 가져오려면 category DB에서 찾아서 만든 후 만들어야함 //이때 category의 Items객체를 통해 맵핑된 categories찾음 private List<Category> categories = new ArrayList<>();
* 실무에서는 중간 테이블이 단순하지 않음
무튼 ManyToMany는 사용금지여~
5. 연관관계 어노테이션 속성
@JoinColumn
출처: JPA기본편(김영한) -인프런 @ManyToOne
출처: JPA기본편(김영한) -인프런 @OneToMany
출처: JPA기본편(김영한) -인프런 @OneToOne
- ManyToOne,OneToMany 모든 속성 가지고 있음