반응형
저번 포스트에서 Entity에 대해서 알아봤으니 이번엔 연관관계에 대한 매핑을 알아보자
1. 엔티티의 연관관계 매핑이란?
- 엔티티의 연관관계 매핑은 객체 간의 관계를 데이터베이스 테이블에 매핑하는 작업을 의미한다. 이를 통해 객체지향적인 프로그래밍 모델을 유지하면서 데이터베이스와의 관계를 표현할 수 있다. JPA에서는 다양한 연관관계 매핑 어노테이션을 제공하여 이를 구현할 수 있다.
연관관계 매핑에는 다음과 같은 어노테이션들이 사용된다.
- @OneToOne:
- 일대일 관계를 매핑한다. 양방향 매핑이 가능하며, 대상 엔티티와 매핑할 때는 @JoinColumn 어노테이션을 사용한다.
- 일대일 관계를 매핑한다. 양방향 매핑이 가능하며, 대상 엔티티와 매핑할 때는 @JoinColumn 어노테이션을 사용한다.
- @OneToMany:
- 일대다 관계를 매핑한다. 단방향 매핑 또는 양방향 매핑으로 설정할 수 있다. 대상 엔티티에는 @ManyToOne 어노테이션을 사용하여 매핑한다.
- 일대다 관계를 매핑한다. 단방향 매핑 또는 양방향 매핑으로 설정할 수 있다. 대상 엔티티에는 @ManyToOne 어노테이션을 사용하여 매핑한다.
- @ManyToOne:
- 다대일 관계를 매핑한다. 대상 엔티티와 매핑할 때는 @JoinColumn 어노테이션을 사용한다.
- 다대일 관계를 매핑한다. 대상 엔티티와 매핑할 때는 @JoinColumn 어노테이션을 사용한다.
- @ManyToMany:
- 다대다 관계를 매핑한다. 양방향 매핑이 가능하며, 연결 테이블을 사용하여 매핑한다.
- 다대다 관계를 매핑한다. 양방향 매핑이 가능하며, 연결 테이블을 사용하여 매핑한다.
추가적인 매핑 옵션
- 지연 로딩/즉시 로딩 설정: 연관된 엔티티를 언제 로딩할지 결정한다.
- 연관관계의 소유자 설정: 양방향 매핑에서 연관관계의 주인을 지정한다.
- 연관관계의 캐스케이드 설정: 연관된 엔티티에 대한 오퍼레이션을 전파한다.
- 연관관계의 페치 전략 설정: 연관된 엔티티를 어떻게 조회할지 전략을 설정한다.
2. 연관관계 매핑 예시
- 다음은 Author 엔티티와 Book 엔티티 간의 일대다 관계를 매핑하는 예시이다.
@Entity
public class Author {
@Id
private Long id;
private String name;
@OneToMany(mappedBy = "author")
private List<Book> books;
// Getters, Setters, Constructors ...
}
@Entity
public class Book {
@Id
private Long id;
private String title;
@ManyToOne
@JoinColumn(name = "author_id")
private Author author;
// Getters, Setters, Constructors ...
}
- 위의 예시에서 Author 엔티티는 @OneToMany 어노테이션을 사용하여 books 필드와 Book 엔티티 간의 일대다 관계를 매핑하였다. Book 엔티티는 @ManyToOne 어노테이션과 @JoinColumn 어노테이션을 사용하여 author 필드와 Author 엔티티 간의 다대일 관계를 매핑하였다.
3. 연관관계 매핑의 중요성
- 연관관계 매핑은 데이터베이스 테이블 간의 관계를 객체로 표현하기 위한 중요한 작업이다. 이를 통해 객체 그래프를 효율적으로 구성하고 데이터베이스와의 일관성을 유지할 수 있으며, 코드의 가독성과 유지보수성을 향상시키고, 객체 지향적인 설계를 가능하게 한다.
객체 지향 프로그래밍과 관계형 데이터베이스의 차이 극복
- 연관관계 매핑을 통해 객체 지향 프로그래밍의 관계와 관계형 데이터베이스의 관계를 일치시킬 수 있다. 이로 인해 개발자는 객체 지향적인 코드 작성에 집중할 수 있으며, 데이터베이스와의 연동 부분은 JPA가 처리하게 된다.
예시 코드
- 다음은 Student와 Course 엔티티 간의 다대다 관계를 매핑하는 예시이다.
@Entity
public class School {
@Id
private Long id;
private String name;
// 일대다 관계: 하나의 학교에 여러 학생이 있을 수 있습니다.
@OneToMany(mappedBy = "school")
private List<Student> students;
// Getters, Setters, Constructors ...
}
@Entity
public class Student {
@Id
private Long id;
private String name;
// 다대일 관계: 여러 학생이 하나의 학교에 소속될 수 있습니다.
@ManyToOne
@JoinColumn(name = "school_id")
private School school;
// Getters, Setters, Constructors ...
}
- 위의 코드에서 School 엔티티는 @OneToMany 어노테이션을 사용하여 students 필드와 Student 엔티티 간의 일대다 관계를 매핑하였다.
- Student 엔티티는 @ManyToOne 어노테이션과 @JoinColumn 어노테이션을 사용하여 school 필드와 School 엔티티 간의 다대일 관계를 매핑하였다.
4. 주의사항
양방향 매핑
- 양방향 매핑은 서로 참조하는 두 엔티티 사이의 관계를 정의한다. 이를 통해 양쪽 엔티티에서 서로의 정보를 쉽게 가져올 수 있다. 하지만, 주의하지 않으면 무한 루프에 빠질 수 있으므로 연관관계의 주인을 명확히 지정해야 한다.
@Entity
public class Parent {
@Id
private Long id;
// 일대다 관계: 하나의 부모에 여러 자식이 있을 수 있습니다.
@OneToMany(mappedBy = "parent")
private List<Child> children;
// Getters, Setters, Constructors ...
}
@Entity
public class Child {
@Id
private Long id;
// 다대일 관계: 여러 자식이 하나의 부모에 소속될 수 있습니다.
@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent;
// Getters, Setters, Constructors ...
}
단방향 매핑
- 단방향 매핑은 한 엔티티에서 다른 엔티티로만 접근이 가능한 관계를 정의한다. 단방향 매핑은 구현이 간단하고 명확하지만, 반대 방향으로의 접근이 필요한 경우 양방향 매핑을 고려해야 한다.
@Entity
public class Teacher {
@Id
private Long id;
private String name;
// Getters, Setters, Constructors ...
}
@Entity
public class Student {
@Id
private Long id;
// 다대일 관계: 여러 학생이 하나의 선생님에 소속될 수 있습니다.
@ManyToOne
@JoinColumn(name = "teacher_id")
private Teacher teacher;
// Getters, Setters, Constructors ...
}
5. 연관관계 매핑의 고급 기능
상속 관계 매핑
- JPA는 엔티티 간의 상속 관계도 매핑할 수 있다. 이를 통해 객체 지향의 상속 개념을 데이터베이스에도 적용할 수 있으며, 코드의 재사용성과 확장성을 높일 수 있다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Vehicle {
@Id
private Long id;
private String manufacturer;
// Getters, Setters, Constructors ...
}
@Entity
public class Car extends Vehicle {
private String model;
// 차량의 모델을 정의합니다.
// Getters, Setters, Constructors ...
}
@Entity
public class Bike extends Vehicle {
private int gearNumber;
// 자전거의 기어 수를 정의합니다.
// Getters, Setters, Constructors ...
}
임베디드 타입 사용
- JPA는 임베디드 타입을 통해 엔티티 내부에 복합 값 타입을 정의할 수 있습니다. 이를 통해 코드의 중복을 줄이고, 도메인 모델의 표현력을 높일 수 있습니다.
@Embeddable
public class Address {
private String street;
private String city;
private String state;
private String zipCode;
// 주소를 정의하는 복합 값 타입입니다.
// Getters, Setters, Constructors ...
}
@Entity
public class Person {
@Id
private Long id;
private String name;
@Embedded
private Address address;
// 임베디드 타입을 사용하여 주소를 매핑합니다.
// Getters, Setters, Constructors ...
}
6. 연관관계 매핑 시 주의사항
성능 최적화
- 연관관계 매핑은 편리하지만, 성능 문제를 일으킬 수 있다. N+1 문제와 같은 성능 이슈를 방지하기 위해 페치 전략을 적절히 설정해야 한다.
@Entity
public class Department {
@Id
private Long id;
private String name;
// 일대다 관계: 하나의 부서에 여러 직원이 있을 수 있습니다.
// FetchType.LAZY를 사용하여 N+1 문제를 방지합니다.
@OneToMany(mappedBy = "department", fetch = FetchType.LAZY)
private List<Employee> employees;
// Getters, Setters, Constructors ...
}
@Entity
public class Employee {
@Id
private Long id;
private String name;
// 다대일 관계: 여러 직원이 하나의 부서에 소속될 수 있습니다.
@ManyToOne
@JoinColumn(name = "department_id")
private Department department;
// Getters, Setters, Constructors ...
}
데이터 무결성 유지
- 연관관계를 잘못 설정하면 데이터 무결성이 깨질 수 있습니다. 연관관계의 방향, 다중성, 제약 조건 등을 정확히 이해하고 적용해야 합니다.
@Entity
public class Order {
@Id
private Long id;
// 다대일 관계: 여러 주문이 하나의 고객에 소속될 수 있습니다.
// NotNull 제약 조건을 사용하여 데이터 무결성을 유지합니다.
@ManyToOne
@JoinColumn(name = "customer_id", nullable = false)
private Customer customer;
// Getters, Setters, Constructors ...
}
@Entity
public class Customer {
@Id
private Long id;
private String name;
// 일대다 관계: 하나의 고객에 여러 주문이 있을 수 있습니다.
@OneToMany(mappedBy = "customer")
private List<Order> orders;
// Getters, Setters, Constructors ...
}
- 위의 예시 코드에서 성능 최적화 부분에서는 FetchType.LAZY를 사용하여 N+1 문제를 방지하였다. 데이터 무결성 유지 부분에서는 nullable = false를 사용하여 NotNull 제약 조건을 적용하였다. 이를 통해 연관관계 매핑 시 성능과 데이터 무결성을 적절히 관리할 수 있다.
7. 결론
연관관계 매핑은 JPA를 사용하는 개발에서 중요한 개념이다.
객체 지향적인 설계와 데이터베이스 설계를 일치시키는 역할을 하며, 이를 통해 풍부하고 유연한 도메인 모델을 구축할 수 있다.
하지만, 성능 최적화와 데이터 무결성 유지 등의 주의사항을 염두에 두어야 하며, 프로젝트의 요구사항에 맞게 적절한 매핑 전략을 선택해야 한다.
2023.08.13 - [JPA] - Spring JPA - Entity
반응형
'Spring Data JPA' 카테고리의 다른 글
Spring JPA - 데이터 영속화란? (0) | 2023.08.13 |
---|---|
Spring JPA - 엔티티를 DTO로 바꿔서 사용하는 이유 (0) | 2023.08.13 |
Spring JPA - Entity (0) | 2023.08.13 |
Spring JPA 영속성 컨텍스트(EntityManager) (0) | 2023.08.13 |
Spring JPA [SpringBoot3.1] - Querydsl 사용 (0) | 2023.08.08 |