Я пытаюсь присоединиться ко второму столу, но он не появляется. Это просто дает мне всех пользователей вместо всех пользователей вместе с FinishedExams.
Это метод в моем репозитории:
public interface IUserRepository extends CrudRepository<User, Integer> {
@Query("SELECT u FROM User u LEFT JOIN FinishedExam f ON u.id = f.user")
List<User> getAllWithExams();
}
В моем FinishedExamController:
@Autowired
private IFinishedExamRepository finishedExamRepository;
@Autowired
private IUserRepository userRepository;
@GetMapping("/allUsersWithExams")
@Fetch(FetchMode.SELECT)
public Iterable<User> getAllUsersWithTheirExams()
{
return userRepository.getAllWithExams();
}
Моя модель пользователя:
@Entity
@Table(name = "users")
public class User implements Serializable {
@Id
@GeneratedValue()
@Column(name = "id")
private int id;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "role_id", nullable = false)
public Role role;
public String getStudentNumber() {
return studentNumber;
}
public void setStudentNumber(String studentNumber) {
this.studentNumber = studentNumber;
}
@Column(name = "student_number", nullable = true)
private String studentNumber;
@Column(name = "first_name", nullable = true)
private String firstName;
@Column(name = "last_name", nullable = true)
private String lastName;
@Column(name = "email", nullable = true, unique = true)
private String email;
@OneToOne(fetch = FetchType.EAGER, mappedBy = "user")
private FinishedExam finishedExam;
@JsonIgnore
@Column(name = "password", nullable = true)
private String password;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "event_users",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "event_id", referencedColumnName = "id")
)
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = createdAt;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
public LocalDateTime getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(LocalDateTime updatedAt) {
this.updatedAt = updatedAt;
}
public String getRole() {
return role.getName();
}
public void setRole(Role role) {
this.role = role;
}
}
Модель сданных экзаменов:
@Entity
@Table(name = "finished_exams")
public class FinishedExam implements Serializable {
@Id
@GeneratedValue()
@Column(name = "id")
private int id;
@OneToOne(fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "exam_id")
private Exam exam;
@Column(name = "finishedExam", nullable = false)
private String finishedExam;
@Column(name = "created_at")
private LocalDateTime createdAt;
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = createdAt;
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
public int getId() {
return id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Exam getExam() {
return exam;
}
public void setExam(Exam exam) {
this.exam = exam;
}
public String getFinishedExam() {
return finishedExam;
}
public void setFinishedExam(String finishedExam) {
this.finishedExam = finishedExam;
}
public void setId(int id) {
this.id = id;
}
public LocalDateTime getCreatedAt() {
return createdAt;
}
public void setCreatedAt(LocalDateTime createdAt) {
this.createdAt = createdAt;
}
public LocalDateTime getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(LocalDateTime updatedAt) {
this.updatedAt = updatedAt;
}
}
Я могу поместить все, что захочу, в предложение ON, но ничего не изменится.
Я включил свою модель пользователя




Вам необходимо указать путь от вашей сущности к целевой сущности, к которой вы хотите присоединиться:
Заменить запрос
@Query("SELECT u FROM User u LEFT JOIN FinishedExam f ON u.id = f.user")
с участием
@Query("SELECT u FROM User u LEFT JOIN u.finishedExam f ON u.id = f.user.id")
Это по-прежнему дает мне тот же результат. Однако, если я добавлю u, f в предложение SELECT, он вернет мне экзамены вместе с ним. Проблема в том, что он возвращает этот [{User: {User, Exams}}] вместо [{User, Exams}]. Что я там не так делаю?
Сообщите мне объект Exams, вы ссылаетесь на неправильное условие where
Я также добавил объект экзаменов
Попробуйте мой отредактированный ответ. Но, кстати, вы выполнили левое соединение без каких-либо условий для класса User, оно все равно вернет всех пользователей, несмотря ни на что. Вы хотите внутреннего соединения?
Мне нужны все пользователи с готовыми экзаменами независимо от того, есть они у них или нет. Я попробовал ваш запрос, но он все равно дает тот же результат.
Если вы просто хотите это сделать, просто используйте метод получения ваших сущностей User: user.getFinishedExam(), потому что ваши сущности отображаются
Прошу прощения за свою глупость. Я только что определил метод getFinishedExam (), но где мне его использовать? в контроллере вместо findAll ()?
Да, сделай это. Он уже сопоставлен и получен (через FetchType.EAGER)
Но я не могу получить доступ к getFinishedExam() через IUserRepository. Это расширение от CrudRepository.
Чувак. Вы должны сначала изучить базовые вещи, прежде чем погрузиться в программирование без каких-либо знаний. В этом случае вы делаете return userRepository.getAllWithExams();. Ваш finishedExam также будет загружен в ваш список пользователей. Если вы хотите получить доступ к finishedExam пользователя, используйте метод getter.
Возможно, я забыл упомянуть об этом, но мне просто нужно, чтобы это было добавлено в API, когда я обращаюсь к /allUsersWithExams вместе с пользователями. Он в режиме EAGER, так что он должен просто появиться, верно? Извини, я не совсем слежу за тобой
Да. Вам не нужен специальный метод. Просто верните userRepository.findAll() и получите все необходимое
Да, но это не так. Это просто дает мне всех пользователей, что проблема
используйте метод findAll()
Да. /user/all использует userRepository.findAll (), но не содержит таблицу finishedExams
После создания методов получения и установки, игнорирования конфликтующих столбцов и перезапуска приложения оно начало работать. Был долгий день, и все начало сбивать с толку.
I can put whatever I want in the ON clause but nothing changes.
Конечно ничего не меняется. Вы выполняете левое соединение в отношении 1: 1, выбирая (только) левый объект и не устанавливая никаких критериев фильтрации для этого объекта. Критерии соединения (да и само соединение) не имеют значения: ваш запрос эквивалентен SELECT u FROM User u.
Возможно, вы хотели вместо этого выполнить внутреннее соединение?
Мне нужны все пользователи с готовыми экзаменами независимо от того, есть они у них или нет.
Поскольку User.finishedExam - это сопоставленная связь, вам не нужно выполнять явное соединение для получения данных экзамена. Просто выберите все User и выполните обычную навигацию по взаимосвязи. Поскольку вы объявили связь с FetchType.EAGER, вам даже не нужно беспокоиться об отсоединении сущностей перед такой навигацией.
Я не понимаю, что вы имеете в виду. Если вы имеете в виду, что я должен пройти userRepository.findAll();, это просто дает мне всех пользователей без экзаменов. Однако они связаны.
@SinanSamet, получив сущности User, вы сможете просто вызвать user.getFinishedExam() для получения связанной сущности FinishedExam, если таковая имеется. Конечно, было бы полезно, если бы вы на самом деле при условии такой геттер (и сеттер тоже). Непонятно, почему вы объявляете свойство, но не имеете доступа к нему.
Я добавил получатель в модель User, но, как я уже сказал в другом ответе, использование userRepository.findAll () возвращает мне только пользователей, но не их таблицу finishedExams.
Покажите класс User, вы должны указать путь для присоединения