2015-01-18 3 views
2

У меня есть 2 объекта: Project и ProjectStatus.JPA CriteriaQuery Order by Last Child Property

Entity проекта:

@Entity 
public class Project { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    Long id; 

    @OneToMany(mappedBy = "project") 
    private List<ProjectStatus> projectStatusses; 
} 

Статус проекта Entity:

@Entity 
public class ProjectStatus { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    Long id; 

    @ManyToOne 
    private Project project; 

    @Enumerated(EnumType.STRING) 
    private ProjectStatusType statusType; 
} 

Я хотел бы заказать проекты по их последним типом состояния с CriteriaQuery.orderBy.

я придумал следующее:

CriteriaQuery<Project> criteriaQuery = criteriaBuilder.createQuery(Project.class); 
Root<Project> root = criteriaQuery.from(Project.class); 
Join<Project, ProjectStatus> join = root.join("projectStatusses", JoinType.LEFT); 
criteriaQuery.orderBy(criteriaBuilder.asc(join.get("statusType"))); 

Я хочу выше запрос только взять последний статус проекта во внимание, но я не знаю, как сделать это. Как я могу это достичь?

Update: SQL, для достижения этой цели является:

SELECT proj.*, stat.statustype 
FROM project proj 
LEFT JOIN projectStatus stat ON proj.id = stat.project_id 
WHERE stat.id = (SELECT MAX(id) FROM projectstatus WHERE project_id = proj.id) 
ORDER BY stat.statustype 
+0

Я не понимаю ** последнего ** типа статуса части. Не могли бы вы прояснить это? –

+0

Конечно, я хочу заказать проекты по значению поля ProjectStatus.statusType самой новой записи ProjectStatus в поле Projects.projectStatusses. – Max

ответ

3

Я не фанат ответа на свой вопрос, но я нашел решение. Надеюсь, это поможет кому-то другому.

Моя ошибка заключалась в поиске решения в методе criteriaQuery.orderBy. Добавление подзапроса в методе criteriaQuery.where сделало трюк.

Решение:

CriteriaQuery<Project> criteriaQuery = criteriaBuilder.createQuery(Project.class); 
    Root<Project> root = criteriaQuery.from(Project.class); 
    Join<Project, ProjectStatus> join = root.join("projectStatusses", JoinType.LEFT); 

    //Create a subquery to get latest ProjectStatus for project 
    Subquery sq = criteriaBuilder.createQuery().subquery(Long.class); 
    Root<T> from = sq.from(Project.class); 
    Path<ProjectStatus> path = root.join("projectStatusses"); 
    //Get latest status 
    sq.select(criteriaBuilder.max(path.<Long>get("id"))); 
    //For each project 
    sq.where(criteriaBuilder.equal(from.<Long>get("id"), root.<Long>get("id"))); 
    Predicate latestStatusCondition = criteriaBuilder.and(criteriaBuilder.equal(join.get("id"), sq)); 

    criteriaQuery.orderBy(criteriaBuilder.asc(join.get("statusType"))); 
    criteriaQuery.where(latestStatusCondition); 
Смежные вопросы