JPA의 표준 스펙에서는 fetch join 대상에 별칭을 줄 수 없다. 그런데 하이버네이트는 허용한다. 즉 fetch join 대상에 별칭을 사용할 수는 있으나 주의할 점이 있다. 주의할 점이라는 것은 조인하는 대상을 필터링하는 행위이다.
설정한 Entity의 관계 Parent(1) : Child(N)
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Parent {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
@BatchSize(size = 5)
@Default
private Set<Child> children = new HashSet<>();
}
@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Child {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
private Parent parent;
}
문제
select p from Parent join fetch p.children c where c.name = :name
이 쿼리를 실행하면 Parent 객체와 관계를 맺고 있던 child가 모두 join되지 않고 name 조건에 맞는 child만 join되게 된다. 이는 별 문제 같지 않아보일 수 있지만 객체의 상태와 DB의 상태 일관성이 깨지는 문제가 발생할 수 있다.
물론 일관성이 깨지더라도 안전하게 조회 용도로만 사용하는 것은 문제가 되지 않는다. 하지만 2차 캐시를 이용하는 경우 엔티티를 조회했을 때 2차 캐시에 의해서 일관성이 깨진 결과가 반환될 수 있으므로 주의해야 한다.
'JPA' 카테고리의 다른 글
같은 클래스와 다대일 양방향 관계 맺기 (0) | 2022.09.01 |
---|---|
OneToOne 정리 (0) | 2022.08.29 |
fetch join과 paging 시 OOM 문제 (OneToOne은 괜찮지) (0) | 2022.08.10 |
JPA에서 발생할 수 있는 문제들과 해결방법 정리 (N + 1, 무작위 JOIN..) (0) | 2022.08.09 |
JPA 동시성 문제 해결하기 (낙관적 락, 비관적 락) (0) | 2022.08.01 |