1:N 단방향
1:N 단방향이란 한 엔티티가 @OneToMany를 통해 여러 엔티티와 관계를 맺는 경우를 말한다.
이 경우 연관관계의 주인은 1에서 가지고 있다.
1:N 단방향 예시
1의 Entity가 외래 키(FK)를 관리한다. ( Company entity가 연관관계의 주인이 된다)
DB 입장에서는 설계상 항상 외래키가 N(Tutor) 쪽에 있어야 한다.
- 하지만 현재 상황에서는 1(Company)이 N(Tutor)의 외래 키를 수정해야 한다.
코드 예시
@Entity
@Table(name = "tutor")
public class Tutor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
public Tutor() {
}
public Tutor(String name) {
this.name = name;
}
}
@Entity
@Table(name = "company")
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "company_id")
private List<Tutor> tutors = new ArrayList<>();
public Company() {
}
public Company(String name) {
this.name = name;
}
public List<Tutor> getTutors() {
return tutors;
}
}
public class Main {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("entity");
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
try {
// Tutor 생성 및 persist
Tutor tutor = new Tutor("wonuk" );
em.persist(tutor);
// Company 생성 및 persist
Company company = new Company("sparta");
// Tutor 테이블에 추가
company.getTutors().add(tutor);
em.persist(company);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
em.close();
}
emf.close();
}
}
실행 결과
마지막에 불필요한 update SQL이 추가적으로 실행되었다.
- 불필요한 SQL은 성능상 단점이다.
Company Entity를 수정했음에도 불구하고 Tutor 테이블이 수정된다.
- 연관관계의 주인이 Company에 있기 때문에 생기는 옳지않은 현상이다.
@JoinColumn 미사용
@Entity
@Table(name = "company")
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany
// @JoinColumn(name = "company_id") 주석처리
private List<Tutor> tutors = new ArrayList<>();
public Company() {
}
public Company(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public List<Tutor> getTutors() {
return tutors;
}
}
실행결과
@JoinColumn 을 사용하지 않으면 중간 테이블 방식을 사용한다.
1:N 양방향
양방향 연관 관계는 하나의 엔티티가 다른 엔티티와 관계를 맺고 그 반대 방향에서도 서로 참조가 가능하도록 설정한 관계이다.
1:N 양방향
연관관계의 주인은 Company이기 때문에 Tutor의 참조용 객체 Company는 읽기 전용 매핑이어야 한다.
- 만약, 양쪽에서 수정이 가능해지면 예측이 불가능해진다.
코드 예시
@Entity
@Table(name = "tutor")
public class Tutor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "company_id", insertable = false, updatable = false)
private Company company;
public Tutor() {
}
public Tutor(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
}
Tutor가 연관관계의 주인이 되지 않도록 insertable = false, updatable = false 설정을 해야한다.
결론
1:N 연관 관계에서 1을 연관관계의 주인으로 만드는 것은 단점만 존재한다.
1:N 연관 관계는 N을 연관관계의 주인으로 만들어주자.