Требуется составить запрос используя CriteriaAPI

Имеется три таблицы, между которыми установлена связь. Adverts связана ManyToOne с Users (по User.id) и Profiles связана OneToOne с Users (по User.id). Требуется сделать выборку Объявлений (Adverts) с максимальным рейтингом пользователя (поле - Profiles.userRank). Использую SpringData. На SQL такой запрос строится легко (выдача правильная):

SELECT * FROM adverts a JOIN users s ON a.user_id=s.id JOIN proiles p ON s.id = p.user_id ORDER BY p.user_rank

Теперь хочу построить этот запрос, используя Criteria Hibernate и метамодель сущностей. Делаю так:

CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Advert> cq = cb.createQuery(Advert.class);
    Root<Advert> root = cq.from(Advert.class);
    //делаем Join с таблицей User по user_id - без ошибок
    root.join(Advert_.user, JoinType.LEFT);
    // пытаюсь сделать join с таблицей Profiles - ОШИБКА в поле Profile_.user (!!!
    root.join(Profile_.user,JoinType.LEFT);
    //что бы потом сделать такой запрос
    CriteriaQuery<Advert> select =
            cq.select(root)
                    .orderBy(
                            cb.desc(root.get(Profile_.userRank) // сортировка по рангу пользователя
                            )
                    );

Вопрос: Как правильно сделать join третьей таблицы (Profiles) и получить из нее (userRank)?

Сущности обозначены так:

@Table(name = "adverts")

public class Advert implements Entity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "adv_topic_id")
private AdvertTopic advertTopic;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "adv_rank_id")
private AdvertRank advertRank;

@Column(name = "adv_type")
@Enumerated(EnumType.STRING)
private Enumes.AdverType advType;

@Column(name = "adv_text")
private String advText;

@Column(name = "adv_price")
private int advPrice;

@Column(name = "adv_date")
private LocalDate advDate;

@Column(name = "adv_status")
@Enumerated(EnumType.STRING)
private Enumes.AdverStatus advStatus;

// USERS

@Table(name = "users")

public class User implements Entity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "login")
private String login;

@Column(name = "password")
private String password;

@Column(name = "role")
@Enumerated(EnumType.STRING)
private Enumes.UserRole role;

// PROFILES

@Table(name = "profiles") public class Profile implements Entity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "user_id")
private User user;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@Column(name = "date_of_birth")
private LocalDate dateOfBirth;

@Column(name = "city")
private String city;

@Column(name = "avatar")
private String avatar;

@Column(name = "money_balance")
private int moneyBalance;

@Column(name = "user_rank")
private int userRank;

Ответы (1 шт):

Автор решения: Knopych

Решил проблему, добавил поле profiles в таблице user. Теперь запрос будет выглядеть так:

CriteriaQuery<Advert> select =
            cq.select(root)
                    .orderBy(
                            cb.desc(root.get("user").get("profile").get("userRank"))
                            )
                    );
→ Ссылка