단방향
📌 단방향 연관관계는 객체 간의 관계가 한쪽에서만 참조 = 일방통행될 수 있는 관계를 말한다. 설정이 단순하고 유지 관리가 쉬우며 불필요한 데이터 접근을 방지할 수 있다.
데이터베이스 중심 객체 설계
- FK 값은 Tutor가 가지고 있다.
- Tutor만 참조할 수 있다.
- N:1, 다대일 연관관계, 가장 많이 사용된다.
- 여러명(N)의 Tutor가 어떤 Company(1)에 소속 되어있는지 설정할 수 있다.
@Entity
@Table(name = "tutor")
public class Tutor {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Column(name = company_id)
private Long companyId;
// 기본 생성자, getter/setter
}
@Entity
@Table(name = "company")
public class Company {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 기본 생성자, getter/setter
}
// Company 생성 및 persist
Company company = new Company("sparta");
em.persist(company);
// Tutor 생성, setCompanyId, persist
Tutor tutor = new Tutor("wonuk");
tutor.setCompanyId(company.getId());
em.persist(tutor);
// IDENTITY 전략을 사용하면 persist()이후 PK를 바로 조회할 수 있다.
Tutor findTutor = em.find(Tutor.class, tutor.getId());
// 조회한 Tutor의 CompanyId로 Company 조회
Long companyId = findTutor.getCompanyId();
Company findCompany = em.find(Company.class, companyId);
- 객체 지향적인 코드를 작성할 수 없다.
- Java Collection을 사용하는 것처럼 tutor.getCompany() 를 사용하지 못한다.
객체 지향 객체 설계
- 객체는 다른 객체를 참조한다.
- N:1 관계는 @ManyToOne, @JoinColumn을 사용한다.
- 코드예시
@Entity
@Table(name = "tutor")
public class Tutor {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// N:1 단방향 연관관계 설정
@ManyToOne
@JoinColumn(name = "company_id")
private Company company;
// 기본 생성자, getter/setter
}
// Company 생성 및 persist
Company company = new Company("sparta");
em.persist(company);
// Tutor 생성, setCompany, persist
Tutor tutor = new Tutor("wonuk");
tutor.setCompany(company);
em.persist(tutor);
// IDENTITY 전략을 사용하면 persist()이후 PK를 바로 조회할 수 있다.
Tutor findTutor = em.find(Tutor.class, tutor.getId());
// 조회한 Tutor의 Company 조회
Company findCompany = findTutor.getCompany();
- Tutor의 FK와 Company의 PK를 @JoinColumn으로 매핑한다.
- Java Collection을 사용하는 것처럼 tutor.getCompany() 를 사용할 수 있다.
양방향
📌 양방향 연관관계는 객체 간의 관계가 양쪽에서 서로를 참조할 수 있는 관계를 의미한다. 이를 통해 양쪽에서 데이터를 쉽게 접근할 수 있지만 관계를 관리할 때 한쪽에서만 연관관계를 설정하거나 삭제하지 않도록 주의가 필요하다.
- 테이블에 변화는 없다.
- Tutor 테이블의 FK로 Company 테이블에 JOIN
- Company 테이블의 PK로 Tutor 테이블에 JOIN
- 사실상 테이블의 연관관계에는 방향의 개념이 없다.
@Entity
@Table(name = "tutor")
public class Tutor {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// N:1 단방향 연관관계 설정
@ManyToOne
@JoinColumn(name = "company_id")
private Company company;
// 기본 생성자, getter/setter
}
@Entity
@Table(name = "company")
public class Company {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// null을 방지하기 위해 ArrayList로 초기화 한다.(관례)
@OneToMany(mappedBy = "company")
private List<Tutor> tutors = new ArrayList<>();
// 기본 생성자, getter/setter
}
- 양방향 연관관계 설정을 위해 mappedBy 속성을 설정한다.
- Tutor의 company 필드와 매핑된다.
// Company 생성 및 persist
Company company = new Company("sparta");
em.persist(company);
// Tutor 생성, setCompany, persist
Tutor tutor = new Tutor("wonuk");
tutor.setCompany(company);
em.persist(tutor);
// IDENTITY 전략을 사용하면 persist()이후 PK를 바로 조회할 수 있다.
Tutor findTutor = em.find(Tutor.class, tutor.getId());
// 조회한 Tutor의 Company 조회
Company findCompany = findTutor.getCompany();
// Company에 속한 Tutor List 조회
List<Tutor> tutors = findCompany.getTutors();
- 반대 방향으로 객체 그래프를 탐색할 수 있다.
양방향 연관관계의 주인
📌 mappedBy는 JPA 양방향 연관관계 설정 시 사용되는 속성으로 두 엔티티 간의 관계에서 연관관계의 주인이 아닌 쪽에 선언한다. 이를 통해 외래 키 관리 책임을 주인 엔티티에 두고 매핑이 중복되지 않도록 한다.
테이블 연관관계
- Tutor ↔ Company (양방향)
- 테이블은 방향이 없다
객체 연관관계
- Tutor → Company N:1 연관관계 (단방향)
- Company → Tutor 1:N 연관관계 (단방향)
- 객체 연관관계는 결국 단방향 연관관계 두개로 양방향이 설정된다.
양방향 연관관계의 주인
- Tutor의 Company를 수정할 때 FK가 수정
- Company의 Tutor를 수정할 때 FK가 수정
- Tutor가 새로운 Company를 간다면?
- Tutor의 참조값 Company 수정
- Company의 참조값 List tutors 수정
- DB 입장에서는 FK만 수정되면 된다. = mappedBy가 없는 쪽이 수정되면 된다.
- 결국, 둘 중 하나로만 외래 키를 관리해야 한다.
- 연관관계의 주인 선정 기준
- 항상 FK가 있는 곳을 연관관계의 주인으로 지정한다.
- Company가 주인인 경우
- Company를 수정할 때 Tutor를 Update하는 SQL이 실행
- 두번의 SQL이 실행되어야 한다. 혼동되기 쉽다.
'DB 접근 > JPA ( Java Persistence API )' 카테고리의 다른 글
연관관계 (0) | 2025.01.12 |
---|---|
[JPA] Spring Data JPA (0) | 2025.01.07 |
[JPA] Entity (1) | 2025.01.05 |
[JPA] 영속성 컨텍스트 (2) | 2025.01.04 |
[JPA] 페러다임 불일치 문제 [객체 관계형 데이터베이스] (1) | 2025.01.02 |