● @ManyToOne, @OneToMany 이란 ?
@ManyToOne과 @OneToMany는 JPA에서 관계형 데이터베이스의 관계를 매핑할 때 사용되는 주된 어노테이션이다.
두 어노테이션을 통해 객체 간의 관계를 표현하고 데이터베이스 테이블 간의 관계를 설정할 수 있다.
● 주요 특징
@ManyToOne
● 다대일 관계를 표현한다. 하나의 엔티티가 여러 다른 엔티티와 관련이 있을 때 사용한다.
● 부모 - 자식 관계에서 자식 엔티티가 부모 엔티티에 속할 때 사용한다.
● 부서엔티티와 직원 엔티티가 있다면, 직원 엔티티에 @ManyToOne 어노테이션을 사용하여 해당 부서를 참조할 수 있다.
@OneToMany
● 일대다 관계를 표현한다. 하나의 엔티티가 여러 다른 엔티티와 관련이 있을 때 사용한다.
● 부모 - 자식 관계에서 부모 엔티티가 여러 자식 엔티티를 가질 때 사용한다.
● 하나의 부서에 여러 직원이 속할 때, 부서 엔티티에 @OneToMany 어노테이션을 사용하여 해당 부서에 속한 직원을 표현한다.
● 속성
@OneToMany
● mappedBy: 양방향 관계를 설정할 때 사용, 관계의 반대쪽에 있는 필드의 이름을 지정한다. 이를 통해 JPA가 매핑을 양방향으로 이해할 수 있다.
● cascade: 연관된 엔티티에 대해 어떤 작업을 수행할 때 함께 수행할 작업을 지정한다. 주로 엔티티의 상태 변화에 대한 영향을 관리하는 데 사용되며, 주요 옵션은 다음과 같습니다:
- CascadeType.ALL: 모든 작업에 대해 캐스케이드 동작을 수행합니다.
- CascadeType.PERSIST: 영속성 컨텍스트에 새로운 엔티티를 추가할 때 캐스케이드 동작을 수행합니다.
- CascadeType.MERGE: 변경된 엔티티를 병합할 때 캐스케이드 동작을 수행합니다.
- CascadeType.REMOVE: 엔티티를 삭제할 때 캐스케이드 동작을 수행합니다.
● fetch: 엔티티를 로딩할 때 사용할 전략을 지정한다. 기본값은 FetchType.LAZY이다.
● FetchType.LAZY: 지연 로딩으로, 필요할 때까지 연관된 엔티티를 로딩하지 않는다.
● FetchType.EAGER: 즉시 로딩으로, 엔티티를 조회할 때 연관된 엔티티를 함께 로딩한다.
@ManyToOne
● fetch: @OneToMany와 동일하게 엔티티를 로딩할 때 사용할 전략을 지정한다.
● cascade: @OneToMany와 동일하게 연관된 엔티티에 대한 작업을 지정한다.
● optional: 연관된 엔티티가 null일 수 있는지 여부를 지정한다.. 기본값은 true이다.
● targetEntity: 연관된 엔티티의 클래스를 지정한다. 주로 다형성을 다룰 때 사용된다.
● 엔티티 설계시 연관관계 주의점
모든 연관관계는 지연로딩으로 설정해야한다.
- 즉시로딩이란? 즉시로딩은 객체를 로드할 때 연관된 객체를 함께 로드하는 전략이다. 관련된 모든 객체가 로드되어 메모리에 올라가기 때문에, 한 번의 쿼리로 모든 연관된 객체를 가져올 수 있다. 즉시로딩을 사용하면 데이터를 가져오는 데 필요한 추가 쿼리가 없으므로 지연로딩보다 성능상 이점이 있을 수 있다. 그러나 즉시로딩을 사용하면 데이터를 요청하지 않았더라도 연관된 모든 데이터가 로드되기 때문에, 불필요한 데이터를 가져올 수 있고 메모리의 부하가 발생해 성능에 영향을 줄 수 있다.
- 지연로딩이란? 지연로딩은 객체가 필요할 때 해당 객체의 데이터를 가져오는 전략이다. 객체가 처음으로 접근되거나 요청될 때 데이터베이스에서 데이터를 로드한다. 객체 그래프를 따라가는 도중에 필요한 시점에 데이터를 로드하기 때문에 초기 로딩 시간이 단축되고, 메모리를 효율적으로 사용할 수 있다. 그러나 여러 번의 추가 쿼리가 발생할 수 있어서 성능 저하의 우려가 있다.
즉시로딩(EAGER)은 예측할 수 없고, 어떤 SQL이 실행되는지 추적하기 어렵다. 특히 JPQL을 실행할 때 N + 1 문제가 자주 발생한다. 연관된 엔티티를 함께 DB에서 조회해야한다면 즉시로딩이 아닌 fetch join 혹은 엔티티 그래프 기능을 사용해야한다.
@OneToMany 클래스 파일이다. default로 Lazy를 사용하고 있다.
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface OneToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default FetchType.LAZY;
String mappedBy() default "";
boolean orphanRemoval() default false;
}
@ManyToOne클래스 파일이다. default로 EAGER를 사용하고 있다.
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManyToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default FetchType.EAGER;
boolean optional() default true;
}
@XToOne (@OneToOne, @ManyToOne)은 default값이 즉시로딩(EAGER)이기 때문에 직접 속성을 사용하여 아래와 같이 설정해줘야 한다.
@ManyToOne(fetch = FetchType.LAZY)
'Web > Spring Boot' 카테고리의 다른 글
| Spring Boot @ResponseBody (1) | 2024.04.04 |
|---|---|
| Spring Boot Welcome Page (0) | 2024.04.03 |
| Spring Boot 라이브러리 (0) | 2024.04.02 |
| Spring Boot 파일 구조 (0) | 2024.04.01 |
| Spring Boot 프로젝트 생성 (0) | 2024.04.01 |