문제
다음과 같은 클래스 구조가 제공됩니다:
class Job
{
String description;
Collection<JobHistory> history;
}
class JobHistory
{
Date assignDate;
User jobOwner;
}
class JobOwner
{
String name;
String id;
}
이 클래스 구조는 JPA를 통해 db에서 액세스할 수 있습니다.DAO 레이어에서는 JPA 구문으로 쿼리를 작성할 수 있습니다.
문제:나는 다음과 같은 목록을 원한다 Job
그리고 JobHistory
주어진 ID를 가진 주어진 소유자에 대한 항목과 마지막 소유자는 누구입니까? Jobhistory
작업의 순서입니다(AssignDate 기준으로 정렬됨).상당히 복잡해 보이지만 어쩌면 더 간단할 수도 있습니다.나에게 일자리를 모두 주고 JobHistory
여기서 지정된 소유자는 작업의 실제 소유자입니다.
업데이트: 명확성을 위해 클래스 이름을 약간 변경하겠습니다.
class Job
{
String description;
Collection<JobOwnerHistory> history;
}
class JobOwnerHistory
{
Date assignDate;
User jobOwner;
}
class JobOwner
{
String name;
String id;
}
모든 Job
소유자의 이력이 다음과 같이 정렬되어 있습니다. assignDate
.실제 소유자는 마지막으로 할당된 작업을 받았습니다(예: MAX(assignDate)
).나는 모든 직업에 대해 다음을 찾고 싶습니다. JobOwnerHistory
으로 입장 MAX(assignDate)
특정 사용자에 대해 User
.
해결책
노력하다:
SELECT j, j.history FROM Job j JOIN User u WHERE u.name = :name
EclipseLink에서 이 작업을 수행하려면 약간 변경해야 합니다.
public List<Job> getAllJobsForUser(String username) {
List<Job> jobs = entityManager
.createQuery("SELECT j FROM Job j JOIN User u WHERE u.name = :name")
.setParameter("name", username)
.setHint(QueryHints.BATCH, "j.history")
.queryForList();
}
차이점?첫 번째 버전에서는 두 개의 개체를 반환하므로 List 또는 Object 배열에서 검색해야 하는 반면, 두 번째 버전에서는 쿼리 힌트가 (아마도) 게으른 일대다 관계에서 모든 작업 기록을 로드합니다. .
Hibernate가 이것과 동등한 것을 가지고 있는지는 모르겠습니다.Toplink Essentials는 그렇지 않습니다.하지만 이는 내가 EclipseLink에서 가장 좋아하는 기능 중 하나입니다.
아 그리고 분명히 제가 했던 것처럼 임시 쿼리 대신 명명된 쿼리를 사용할 수 있습니다(아마도 그렇게 해야 합니다). 왜냐하면 이러한 쿼리는 빌드 중에 확인할 수 있기 때문입니다.
다른 팁
쿼리에 대한 다음 답변을 찾았습니다.
SELECT j, h FROM Job j JOIN j.history h JOIN h.jobOwner u
WHERE u.name = :name AND
(SELECT MAX(h2.assignDate) FROM Job j2 JOIN j2.history h2
WHERE h2 member of j.history) = h.assignDate
쿼리에서 가장 중요한 부분은 SubSelect입니다. MAX(h2.assignDate)
나는 직장과 소유자 역사에서 최신 항목을 얻고 싶기 때문입니다.