다대일은 이전글에서 만들었던 Member, Team 구조가 ManyToOne 구조이다.
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
Member쪽이 주인이 된다.
Team도 만약 거꾸로 Member로 가보고싶다면 양방향 설계를 하면 된다.
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
아까 만든 Member Team에서 Team을 중심으로 무언가를 한다고 하면 OneToMany가 된다.
하지만 DB쪽에서는 다를 가진 테이블에 FK를 설정해야한다.
try {
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setUsername("UserA");
em.persist(member);
team.getMembers().add(member);
tx.commit();
}
일대다 관계를 만들고 이런 쿼리를 작성해서 실행해보면,
이렇게 db에는 정상적으로 나가는것을 볼 수 있지만, FK가 member테이블에 있어서 member 테이블 업데이트 없이는 Team에다가 member를 어떻게 할 수가 없다. 따라서 query가 update에 한번 더 나가게 되고 이는 추후 성능저하가 될 수 있다.
일대일관계는 아무대나 외래키를 넣어도 된다.
주 테이블에 넣거나, 대상 테이블에 넣거나 한가지를 선택해야한다. 또한 외래키에 데이터베이스 유니크 제약조건이 추가해야한다.
@Entity
public class Locker {
@Id @GeneratedValue
private long id;
private String name;
@OneToOne(mappedBy = "locker")
private Member member;
}
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@OneToOne
@JoinColumn(name = "LOCKER_ID")
private Locker locker;
}
Locker와 Member는 1대1 관계이다.
이 방식이 가장 간단한 연관관계이고 양방향의 경우 똑같이 반대편에 mappedBy를 넣어주면 된다.
다대다의 경우 객체는 컬랙션을 이용해서 객체 2개로 다대다를 구현한다.
테이블의 경우 가운데 테이블을 만들어서 매핑을 해준다.
이는 매우 편리해보이지만, 실무에서는 사용할수가 없다.
연결테이블이 단순하게 연결하고 끝나지 않고 안에 추가데이터가 들어가야해서 문제가 발생한다.
따라서 엔티티 연결용 테이블을 직접 만들어서 사용하는것이 권장된다.