반응형
다중성과 연관관계 종류
다대일
- 현재 객체는 하나의 객체를 참조할 수 있는 구조
1, 단방향
@Entity
public class User {
@Id
@GeneratedValue
@Column(name = "user_id")
private Long id;
private String username;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="team_id") // 연과관계의 주인이 되는 곳
private Team team;
// .. codes
}
@Entity
public class Team {
@Id
@GeneratedValue
@Column(name = "team_id")
private Long id;
private String name;
}
- 양방향
@Entity
public class User {
@Id
@GeneratedValue
@Column(name = "user_id")
private Long id;
private String username;
@ManyToOne(fetch = FetchType.LAZY) // 연관관계 주인
@JoinColumn(name="team_id")
private Team team;
// .. codes
}
@Entity
public class Team {
@Id
@GeneratedValue
@Column(name = "team_id")
private Long id;
private String name;
@OneToMany(mappedBy = "team") // user 객체의 필드 변수 이름
private List<User> users = new ArryaList<>();
}
- 앵간하면 왜래키가 존재하는 entity를 주인으로 해주면 좋습니다 -> 실제 reference key의 위치를 entity를 보고 이해할 수 있기 때문
- 편의 method 인 changeTeam이나 addUser를 호출하게 되면 무한 루프를 발생시킬 수 있기 때문에 구현할때 조심해야 합니다.
일대다
- 현재 entity객체가 여러개를 참조할 수 있는 구조
- collection 프레임 워크의 정보 중 1개를 사용
- 다대일 의 Team이라고 생각하면 됩니다
- 주로 team에서 mappedBy를 사용해서 거울 역할만 하게 해야지 좋습니다. -> 연관관계 주인을 설정하기 위해서
- 단점
- 외래키가 다른 table에 존재 -> mappedBy 사용해서 거울로 바꾸기
- 외래키가 다른 table 에 존재 하기 때문에 insert sql를 생성하게 되면, 다른 reference 객체의 table에 update query를 날려야 해서 서능 이슈 발생
일대일
- 특징
- refernec key를 가지고 주 테이블과 부 테이블 모두 원하는 정보를 조회 가능
- 외래키를 두는 위치
- 개발자 관점 : 주테이블에 위치
- 객체 참조와 외래키 참조의 모습이 비슷해서 선호
- DBA관점 : 부 테이블에 위치
- 나중에 OneToOne에서 OneToMany 로 구조를 바꿀 때 테이블 변경 없이 사용 가능합니다
- 단방향
- JPA는 부 Table의 외래키가 존재하고, 주 Table Entity객체에 연관관계를 설정할 수 없게 맊아 놨습니다
- 이 구조를 설정하고 싶다면 양방향 관계를 해야합니다.
- 양방향 구조
- 위에서 언급한 것과 동일하게 부 table에 외래키가 존재할 경우 사용하는 구조 입니다
다대다
- table구조에서는 연결 테이블이 추가되는 형태이다
@ManyToMany
로 연결
- 단방향
@Entity
public class User {
@Id
@GeneratedValue
@Column(name = "user_id")
private Long id;
private String username;
@ManyToMany
@JoinTable(name = "user_role",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
Set<Role> roles = new HashSet<>();
}
@Entity
public Role role {
@Id
@GeneratedValue
@Column(name = "role_id")
private Long id;
private String name;
}
@JoinTable.name
: 연결 테이블 지정, 현재 예시 에서는user_role
로 설정했습니다.@JoinTable.joinColumns
: 현재 User table를 Mapping 할 Column이름을 설정합니다. 현재 예시에는 user_id로 설정했습니다.@JoinTable.inverseJoinColumns
: 반대 방향의 table을 참조할 연결 테이블의 column 명을 설정하기 위해서 사용합니다. 현재 예시 에서는role_id
로 설정 했습니다.- 위의 구조로 인해서
user_role
이라는 table 은user_id
,role_id
를 가지게 됩니다.
- 위의 구조로 인해서
- 양방향
@Entity
public class User {
@Id
@GeneratedValue
@Column(name = "user_id")
private Long id;
private String username;
@ManyToMany
@JoinTable(name = "user_role",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
Set<Role> roles = new HashSet<>();
}
@Entity
public Role role {
@Id
@GeneratedValue
@Column(name = "role_id")
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private List<User> users = new ArryayList<>();
}
- 한계점
- 연결 테이블의 정보를 확장하기 어렵습니다.
- 만약 회원 권한 정보가 변경된 시점을 알고싶을 경우
user_role
table에updatetime
이나,insertdate
column 이 필요하지만 확인할 수 없습니다. - 해결법
- 중간에 연결 테이블을 실제 Entity class로 만듭니다
- User와 Role과 MnayToOne 관계로 Mapping 합니다
- UserRole 이라는 Entity 객체를 확장할 수 있기 때문에 더 좋은 구조입니다.
- 연결 Table 코드
@Entity
@IdClass(UserRoleId.class)
public class UserRole {
@Id
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@Id
@ManyToOne
@JoinColumn(name = "role_id")
private Role role;
private LocalDatetime inserttime;
}
public class UserRoleId implements Serializable {
private String user;
private String role;
@Overrid
public boolean equals(Object o) {
//... equal code
}
@Overrid
public int hashCode() {
// ...
}
}
- 복합키
- 별도의 식별자 Id를 class로 생성해야합니다.
- 영속성 컨택스트에서 Map 과 같은 곳에 저장하게 되는데 그때 데이터를 식별할 수 있도록 hashCode와 equals를 재저의 해야합니다.
- 복합 key 객체는 default 생성자가 있어야합니다.
- @IdClass외에 @EmbeddedId를 사용하는 경우도 존재합니다
- 복합키를 사용한 Id 는 나중에 클러스터 키로인해 변경이되면 성능 이슈로 이어질 수 있습니다. 그러므로 새로운
대리키
를 사용하는 것을 권장 합니다.
반응형
'JPA > ORM 표준 JPA' 카테고리의 다른 글
Atomic Query 작성 (0) | 2022.04.28 |
---|---|
Fetch Join 별칭 이슈 (2) | 2022.01.22 |
05 연관관계 (0) | 2021.07.28 |
04 Entity (3) | 2021.07.08 |
03. 영속성 (0) | 2021.06.30 |