연관관계를 매핑할 떄 고려해야하는 3가지 사항

  1. 다중성
  2. 단방향, 양방향
  3. 연관관계의 주인

 

다중성의 종류

  1. 다대일: @ManyToOne
  2. 일대다: @OneToMany
  3. 일대일: @OneToOne
  4. 다대다: @ManyToMany

 

 

@OneToMany

 

 

외래키를 매핑하는 방법

@JoinColumn 

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

 

 

@OneToOne

 

일대일 관계는 그 반대도 일대일이다.

일대일 관계는 주 테이블이나 대상테이블 중 외래 키를 넣을 테이블을 선택할 수 있다.

외래 키에 DB 유니크 제약 조건을 추가해야 일대일 관계가 된다.

 

다대일 단방향 관계 매핑과 JPA어노테이션만 달라지고 거의 유사하다

 

@OneToOne 단방향 예시 코드

일대일 관계에서 대상 테이블에 외래 키를 지정하는 단방향 관계는 JPA에서 지원하지 않는다.

 

    class Member{
        //연관관계 주인 클래스, One

        @Id
        @Column(name = "MEMBER_ID")
        private Long id;

        private String username;

        @OneToOne
        @JoinColumn(name="TEAM_ID")
        private Team team; //Team 객체와 연관관계를 맺음
    }
    class Team{
        //One

        @Id
        @Column(name = "TEAM_ID")
        private Long id;

        private String name;

    }

 

@OneToOne 양방향 예시 코드

 

주 테이블은 멤버 테이블이지만, 외래 키를 대상 테이블에서 관리하고 주 테이블의 team 필드는 읽기 전용이 된다.

 

class Member{
    //연관관계 주인 클래스, One

    @Id
    @Column(name = "MEMBER_ID")
    private Long id;

    private String username;

    @OneToOne
    @JoinColumn(name="TEAM_ID")
    private Team team; //Team 객체와 연관관계를 맺음
}
class Team{
    //One

    @Id
    @Column(name = "TEAM_ID")
    private Long id;

    private String name;

    @OneToOne(mappedBy = "team") //Member 클래스의 team과 연관관계 맺음
    private Member member; //양방향 매핑
}

 

@ManyToMany

 

실무에서는 사용을 최대한 하지않는다.

관계형 DB에서는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.

연결 테이블을 추가하여 일대다 또는 다대일 관계로 변경해야 한다.

 

객체는 컬렉션을 사용해 객체 2개로 다대다 관계가 가능하다.

개발 할 때 연결 테이블이 단순 연결만 하는 것이 아닌 추가 데이터가 많이 들어갈 수 있는데

이때 매핑 정보만 넣는 것이 가능하고 추가 정보를 넣는 것 자체가 불가능하다(확장 불가)

또 한 중간 테이블이 숨어져 있기 때문에 예상하지 못한 쿼리문들이 나갈 수 있다.

아래는 사용을 하지 말아야할 @ManyToMany코드이다.

 

@ManyToMany 단방향

 

class Member{
    //연관관계 주인 클래스, MANY

    @Id
    @Column(name = "MEMBER_ID")
    private Long id;

    private String username;

    @ManyToMany
    @JoinTable(name = "Member_Team",//연결 테이블 지정
                joinColumns = @JoinColumn(name = "MEMBER_ID"), //현재 방향인 회원
                inverseJoinColumns = @JoinColumn(name = "TEAM_ID"))//반대 방향인 TEAM
    private List<Team> teams = new ArrayList<>();
}
class Team{
    //MANY

    @Id
    @Column(name = "TEAM_ID")
    private Long id;

    private String name;


}

 

@ManyToMany 양방향

class Member{
    //연관관계 주인 클래스, MANY

    @Id
    @Column(name = "MEMBER_ID")
    private Long id;

    private String username;

    @ManyToMany
    @JoinTable(name = "Member_Team",//연결 테이블 지정
                joinColumns = @JoinColumn(name = "MEMBER_ID"), //현재 방향인 회원
                inverseJoinColumns = @JoinColumn(name = "TEAM_ID"))//반대 방향인 TEAM
    private List<Team> teams = new ArrayList<>();
}
class Team{
    //MANY

    @Id
    @Column(name = "TEAM_ID")
    private Long id;

    private String name;

    @ManyToMany(mappedBy = "teams")
    private List<Member> members = new ArrayList<>();
}

 

@ManyToMany 한계 극복

 

연결 테이블용 엔티티를 추가하여 연결 테이블을 엔티티로 만들어 준다

각 두 테이블을 일대다, 다대일로 관계를 설정 해 준다.

 

class Member{
    //One

    @Id
    @Column(name = "MEMBER_ID")
    private Long id;

    private String username;

    @OneToMany(mappedBy = "member")
    private List<Member_Team> member_teams = new ArrayList<>(); //중간 테이블 연결
}
class Team{
    //One

    @Id
    @Column(name = "TEAM_ID")
    private Long id;

    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member_Team> members = new ArrayList<>(); //중간 테이블 연결
}


class Member_Team{
    //Many
    //연관관계 주인

    @Id
    @GeneratedValue
    private Long id;

    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;

    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;
}

+ Recent posts