[자바 ORM 표준 JPA 프로그래밍] 5.1 단방향 연관관계
개발서적/자바 ORM 표준 JPA

[자바 ORM 표준 JPA 프로그래밍] 5.1 단방향 연관관계

Reference. 자바 ORM 표준 JPA 프로그래밍

책 목차 및 이전 글

들어가기 전

  • 객체는 참조, 테이블은 외래 키를 사용하여 관계 구성
  • 방향(Direction):
    • 단방향 관계: 객체에서 한쪽만 참조하는 것을 의미 (회원→팀 or 팀→회원)
    • 양방향 관계: 모두 서로 참조하는 것을 의미(회원→팀 and 팀→회원)
    • 테이블 관계는 항상 양방향
  • 다중성(Multiplicity):
    • 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M)
  • 연관관계의 주인(owner):
    • 객체를 양방향 연관관계로 만들면 연관관계의 주인이 필요

단방향 연관관계

  • 회원과 팀이 있다.
  • 회원은 하나의 팀에만 소속될 수 있다.
  • 회원과 팀은 다대일 관계이다.
  • 객체 연관관계
    • 회원 객체는 Member.team 필드로 팀 객체 참조(주소)와 연관관계 구성
    • 회원 객체와 팀 객체는 단방향 관계, member→team은 가능 team→member 불가능
  • 테이블 연관관계
    • 회원 테이블은 TEAM_ID 외래키로 연관관계 구성
    • 회원 테이블과 팀 테이블은 양방향 관계, TEAM_ID로 양방향 JOIN 가능
    --두 쿼리 모두 동일한 결과
    SELECT *
    FROM MEMBER M
    JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
    
    SELECT *
    FROM TEAM T
    JOIN MEMBER M ON T.TEAM_ID = M.TEAM_ID
  • 객체 연관관계와 테이블 연관관계의 가장 큰 차이
    • 참조를 통한 연관관계는 언제나 단방향
    • 양방향으로 만들려면 반대쪽에도 필드를 추가
      • 정확히 양방향 관계가 아닌 서로 다른 단방향 관계 2개로 구성
    //--------단방향 관계
    class A {
    		B b;
    }
    class B {}
    
    //--------양방향 관계
    class A {
    		B b;
    }
    class B {
    		A a;
    }

5.1.1 순수한 객체 연관관계

  • 객체 그래프: 객체가 참조를 사용해 연관관계를 탐색하는 것을 의미
public class Member {
 
 private String id;
 private String username;
 
 private Team team;
 
 // 연관관계 설정
 public void setTeam(Team team) {
   this.team = team;
 }
 
 // Getter, Setter ...
}

public class Team {
  
  private String id;
  private String name;

  // Getter, Setter ...
 
}
public static void main(String[] args){
	
		Member member1 = new Member("member1", "회원1");
		Member member2 = new Member("member2", "회원2");
		Team team1 = new Team("team1", "팀1");
		
		member1.setTeam(team);
		member2.setTeam(team);
		
		Team findTeam = member1.getTeam();
}

5.1.2 테이블 연관관계

  • 조인: 외래키를 사용해서 연관관계를 탐색
--테이블 DDL
CREATE TABLE MEMBER (
    MEMBER_ID VARCHAR(255) NOT NULL,
    TEAM_ID VARCHAR(255),
    USERNAME VARCHAR(255),
    PRIMARY KEY (MEMBER_ID)
)
CREATE TABLE TEAM (
    TEAM_ID VARCHAR(255) NOT NULL,
    NAME VARCHAR(255),
    PRIMARY KEY (TEAM_ID)
)
ALTER TABLE MEMBER ADD CONSTRAINT FK_MEMBER_TEAM
    FOREIGN KEY (TEAM_ID) REFERENCES TEAM;
--팀, 회원 등록
INSERT INTO TEAM(TEAM_ID, NAME) VALUES('team1', '팀1');
INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME)
VALUES('member1', 'team1', '회원1');
INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME)
VALUES('member2', 'team1', '회원2');

--회원1이 소속된 팀 조회
SELECT T.*
FROM MEMBER M
	JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
WHERE M.MEMBER_ID = 'member1'

5.1.3 객체 관계 매핑

@Entity
pubilc class Member {
    @Id
    @Column(name = "MEMBER_ID")
    private String id;

    private String username;

    //연관관계 매핑
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;

		//연관관계 설정
		public void setTeam(Team team){
				this.team = team;
		}

		//Getter, Setter ...
}

@Entity
pubilc class Team {
    @Id
    @Column(name = "TEAM_ID")
    private String id;

    private String name;

		//Getter, Setter ...
}
  • 객체 연관관계: 회원 객체의 Member.team 필드 사용
  • 테이블 연관관계: 회원 테이블의 MEMBER.TEAM_ID 외래 키 컬럼 사용

5.1.4 @JoinColumn

  • 외래 키를 매핑할 때 사용 (생략 가능)

@JoinColumn의 주요 속성

속성 기능 기본값
name 매핑할 외래 키 이름 필드명+_+참조 테이블 기본 키 컬럼명
referencedColumnName 외래 키가 참조하는 대상 테이블의 컬럼명 참조하는 테이블의 기본키 컬럼명
foreignKey(DDL) 외래 키 제약조건을 직접 지정 이 속성은 테이블 생성할 때만 사용  
unique,
nullable,
insertable,
updatable,
columnDefinition,
table
@Column 속성과 동일  

<참고>

  • @JoinColumn 생략
    • 기본 전략: 필드명 + _ + 참조하는 테이블의 컬럼명
    • 예) 필드명(team) + _(밑줄) + 참조하는 테이블의 컬럼명(TEAM_ID) = team_TEAM_ID
    @ManyToOne
    private Team team;

5.1.5 @ManyToOne

  • 다대일(N:1) 매핑 정보, 연관관계를 매핑할때 다중성을 나타내는 어노테이션 (필수)

@ManyToOne 속성

속성 기능 기본값
optional false로 설정하면 연관된 엔티티가 항상 존재 true
fetch 글로벌 패치 전략을 설정 (8장 참고) - @ManyToOne=FetchType.EAGER
- @OneToMany=FetchType.LAZY
cascade 영속성 전이 기능을 사용 (8장 참고)  
targetEntity 연관된 엔티티 타입 정보를 설정. 이 기능은 거의 사용하지 않고 컬렉션을 사용해도 타입 정보를 알 수 있음