[java] JPA와 Hibernate를 사용할 때 JOIN과 JOIN FETCH의 차이점은 무엇입니까?

정규 JOIN 사용 위치와 JOIN FETCH 위치를 이해하도록 도와주세요.

예를 들어이 두 쿼리가

FROM Employee emp
JOIN emp.department dep

FROM Employee emp
JOIN FETCH emp.department dep

그들 사이에 차이점이 있습니까? 그렇다면 어느 것을 사용해야합니까?



답변

이 두 쿼리에서는 JOIN을 사용하여 하나 이상의 부서가 연결된 모든 직원을 쿼리합니다.

그러나 차이점은 첫 번째 쿼리에서 최대 절전 모드에 대한 고용 만 반환한다는 것입니다. 두 번째 쿼리에서는 고용 관련 부서를 모두 반환합니다 .

따라서 두 번째 쿼리를 사용하는 경우 데이터베이스를 다시 방문하여 각 직원의 부서를 확인하기 위해 새 쿼리를 수행 할 필요가 없습니다.

각 직원의 부서가 필요할 때 두 번째 쿼리를 사용할 수 있습니다. 부서가 필요하지 않은 경우 첫 번째 쿼리를 사용하십시오.

WHERE 조건을 적용 해야하는 경우이 링크를 읽으십시오 (필요한 것) : JPQL “join fetch”를 “where”절과 함께 JPA 2 CriteriaQuery로 올바르게 표현하는 방법 은 무엇 입니까?

최신 정보

사용하지 않고 fetch부서가 계속 반환되는 경우 Employee와 Department (a @OneToMany) 간의 매핑이로 설정되어 있기 때문 입니다 FetchType.EAGER. 이 경우 모든 HQL fetch쿼리가 있거나없는 쿼리가 FROM Employee모든 부서를 가져옵니다. 모든 맵핑 * ToOne ( @ManyToOne@OneToOne)은 기본적으로 EAGER 입니다.


답변

에서 이 링크 내가 주석에 앞서 언급,이 부분을 읽어

“페치”조인을 사용하면 단일 선택을 사용하여 연관 또는 값의 콜렉션을 상위 오브젝트와 함께 초기화 할 수 있습니다. 이것은 컬렉션의 경우에 특히 유용합니다. 연관 및 콜렉션에 대한 맵핑 파일의 외부 결합 및 지연 선언을 효과적으로 대체합니다 .

이 “JOIN FETCH”는 엔터티 내부의 컬렉션에 대해 (fetch = FetchType.LAZY) 속성이있는 경우 효과가 있습니다 (예 : 아래).

그리고 “쿼리가 발생할 때”의 방법에만 영향을 미칩니다. 그리고 당신도 이것을 알아야 합니다 :

최대 절전 모드에는 두 가지 직교 개념이 있습니다. 연결은 언제 가져오고 어떻게 가져 옵니까? 혼동하지 않는 것이 중요합니다. 가져 오기를 사용하여 성능을 조정합니다. 지연을 사용하여 특정 클래스의 분리 된 인스턴스에서 항상 사용 가능한 데이터에 대한 계약을 정의 할 수 있습니다.

연결이 언제 페치되는지-> “FETCH”유형

어떻게 가져 오는가-> Join / select / Subselect / Batch

귀하의 경우 FETCH는 직원 내부에 부서로 부서가있는 경우에만 효과가 있습니다.

@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;

당신이 사용할 때

FROM Employee emp
JOIN FETCH emp.department dep

당신은 얻을 것이다 empemp.dep. 페치를 사용하지 않아도 여전히 얻을 수는 emp.dep있지만 최대 절전 모드는 데이터베이스에 대한 다른 선택을 처리하여 해당 부서 세트를 가져옵니다.

따라서 성능 조정의 문제, 단일 쿼리 (열심 한 페칭)로 모든 결과를 얻거나 (필요한지 여부) 원하는 경우 후자의 쿼리를 원합니다 (지연 페치).

한 번의 select (하나의 큰 쿼리)로 작은 데이터를 가져와야 할 경우 열성적인 페칭을 사용하십시오. 또는 lazy fetching을 사용하여 후자에 필요한 것을 쿼리하십시오 (많은 더 작은 쿼리).

다음과 같은 경우 인출을 사용하십시오.

  • 당신이 얻으려고하는 엔티티 내부에 큰 불필요한 수집 / 세트가 없습니다.

  • 응용 프로그램 서버에서 데이터베이스 서버로의 통신이 너무 길고 오랜 시간이 필요함

  • 당신은 (는 IT에 대한 액세스 권한이 없을 때 당신은 후자 해당 모음을해야 할 수도 있습니다 외부트랜잭션 방법 / 클래스)


답변

붙다

사용할 때 JOIN엔티티 연관에 대해 하는 경우 JPA는 생성 된 SQL 문에서 상위 엔티티와 하위 엔티티 테이블간에 JOIN을 생성합니다.

따라서이 JPQL 쿼리를 실행할 때 예를 들어보십시오.

FROM Employee emp
JOIN emp.department dep

최대 절전 모드는 다음 SQL 문을 생성합니다.

SELECT emp.*
FROM employee emp
JOIN department dep ON emp.department_id = dep.id

SQL SELECT절은 employee테이블 열만 포함하고 테이블 열 은 포함 하지 않습니다 department. department테이블 열 을 가져 오려면 JOIN FETCH대신 대신 사용해야 합니다 JOIN.

FETCH 가입

그래서, 비교 JOIN의는 JOIN FETCH당신이에 가입 테이블 열을 투사 할 수 있습니다 SELECT생성 된 SQL 문 절.

따라서 귀하의 예 에서이 JPQL 쿼리를 실행할 때 :

FROM Employee emp
JOIN FETCH emp.department dep

최대 절전 모드는 다음 SQL 문을 생성합니다.

SELECT emp.*, dept.*
FROM employee emp
JOIN department dep ON emp.department_id = dep.id

이번에 departmentFROMJPQL 절에 나열된 엔티티와 연관된 컬럼뿐만 아니라 테이블 컬럼도 선택됩니다 .

또한 가져 오는 주 엔터티와 함께 ​​페칭 전략을 사용하여 엔터티 연결을 초기화 할 수 있으므로 Hibernate를 사용할 때 문제 JOIN FETCH를 해결하는 좋은 방법 입니다.LazyInitializationExceptionFetchType.LAZY


답변

당신이있는 경우 @oneToOne에 매핑 설정을 FetchType.LAZY하고 무엇 Hibernate는 할 것 (당신이 부서 직원의 일부 객체로로드 할 객체를 필요로하기 때문에) 당신이 두 번째 쿼리를 사용하여,이 부서는 DB에서 가져 오는 모든 개별 직원 개체에 대한 개체를 가져 오기 위해 쿼리를 발행합니다.

나중에 코드에서 Employee to Department 단일 값 연결을 통해 Department 객체에 액세스 할 수 있으며 Hibernate는 지정된 Employee에 대한 Department 객체를 가져 오기 위해 쿼리를 발행하지 않습니다.

Hibernate는 여전히 가져온 직원 수와 동일한 쿼리를 발행합니다. 모든 Employee 객체의 Department 객체에 액세스하려는 경우 Hibernate는 위의 두 쿼리에서 동일한 수의 쿼리를 발행합니다.


답변

Dherik : fetch를 사용하지 않을 때 결과는 다음과 같은 유형이됩니다. List<Object[ ]>이는 직원 목록이 아닌 Object 테이블 목록을 의미합니다.

Object[0] refers an Employee entity
Object[1] refers a Departement entity 

가져 오기를 사용하는 경우 하나의 선택 만 있고 결과는 List<Employee>부서 목록을 포함하는 직원 목록입니다. 엔티티의 지연 선언을 대체합니다.


답변