용어
1. 방향 (Direction) : 단방향, 양방향
2. 다중성 (Multiplicity) : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M) 이해
3. 연관관계의 주인 (Owner) : 객체 양방향 연관관계는 관리 주인이 필요
예시 시나리오
- 회원과 팀이 존재
- 회원은 하나의 팀에만 소속
- 회원과 팀은 다대일 관계
@Entity
class Member(
@Id
@GeneratedValue()
@Column(name = "MEMBER_ID")
val id: Long = 0,
@Column(name = "USERNAME")
var username: String,
@Column(name = "TEAM_ID")
var teamId: Long
)
val team = Team(name = "TeamA")
em.persist(team)
val member = Member(
username = "member1",
teamId = team.id
)
em.persist(member)
// 조회
val findMember = em.find(Member::class.java, member.id)
// 연관관계가 없음
val findTeam = em.find(Team::class.java, findMember.teamId)
tx.commit()
@Entity
class Member(
@Id
@GeneratedValue()
@Column(name = "MEMBER_ID")
val id: Long = 0,
@Column(name = "USERNAME")
var username: String,
@ManyToOne
@JoinColumn(name = "TEAM_ID")
val team: Team
)
val team = Team(name = "TeamA")
em.persist(team)
val member = Member(
username = "member1",
team = team
)
em.persist(member)
val findMember = em.find(Member::class.java, member.id)
val findTeam = findMember.team
tx.commit()
회원(Member)과 팀(Team)은 N:1 관계
회원에서 팀을 조회(객체 그래프 탐색)할 수 있고, 팀에서도 해당하는 회원들을 조회할 수 있어야 함
즉, 양방향 연관관계가 형성
아래 Team 엔티티 코드를 보면 Member 객체를 받는 컬렉션이 추가됨
그로인해 Team 엔티티를 통해 Member 를 조회할 수 있음 (즉, 반대 방향 객체 그래프 탐색)
-> Team 엔티티와 Member 엔티티는 1:N 이기 때문에, @OneToMany를 지정
-> mappedBy 값은 Member 엔티티에 정의된 Team 변수 이름으로 지정
class Team(
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
val id: Long? = null,
var name: String,
@OneToMany(mappedBy = "team")
val members: MutableList<Member> = arrayListOf()
)
// Main
// Team 조회
val findTeam = em.find(Team::class.java, team.id)
// Team 에 속한 Member 조회
val members: MutableList<Member> = findTeam.members
객체의 양방향 관계일 때 어떤 객체에서 외래키를 관리해야 하는가?
객체의 두 관계중 하나를 연관관계의 주인으로 지정
연관관계의 주인만이 외래 키를 관리(등록, 수정)
주인이 아니면 mappedBy 속성으로 주인 지정하고, 읽기(Read)만 가능
외래키가 있는 곳을 주인으로 지정하기
-> 회원(Member) 엔티티 안에 팀(Team) 외래키가 있으니, 회원 엔티티가 주인이 됨
양방향 매핑시, 항상 순수 객체 상태를 고려해서 연관관계 주인, 주인이 아닌 엔티티 즉 양쪽에 값을 설정
-> 연관관계 편의 메소드를 생성 (아래 예시 코드)
@ManyToOne
@JoinColumn(name = "TEAM_ID")
lateinit var team: Team
fun updateTeam(team: Team) {
this.team = team
team.members.add(this)
}