Требуется составить запрос используя 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 шт):
Решил проблему, добавил поле profiles в таблице user. Теперь запрос будет выглядеть так:
CriteriaQuery<Advert> select =
cq.select(root)
.orderBy(
cb.desc(root.get("user").get("profile").get("userRank"))
)
);