연관관계를 매핑할 떄 고려해야하는 3가지 사항
- 다중성
- 단방향, 양방향
- 연관관계의 주인
다중성의 종류
- 다대일: @ManyToOne
- 일대다: @OneToMany
- 일대일: @OneToOne
- 다대다: @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;
}'Spring' 카테고리의 다른 글
| [Spring Security] UserDetails (0) | 2023.04.18 |
|---|---|
| [Spring Security] 패스워드 암호화(PasswordEncoder) (0) | 2023.04.17 |
| [Spring JPA] 다양한 연관관계 매핑(@OneToMany) (0) | 2023.04.14 |
| [Spring JPA] 다양한 연관관계 매핑(@ManyToOne) (0) | 2023.04.10 |
| [Spring JPA] 단방향, 양방향 연관관계 (0) | 2023.04.09 |