Не могу уйти, присоединиться ко второму столу

Я пытаюсь присоединиться ко второму столу, но он не появляется. Это просто дает мне всех пользователей вместо всех пользователей вместе с 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, но ничего не изменится.

Покажите класс User, вы должны указать путь для присоединения

Mạnh Quyết Nguyễn 19.05.2018 19:50

Я включил свою модель пользователя

Sinan Samet 19.05.2018 19:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
42
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вам необходимо указать путь от вашей сущности к целевой сущности, к которой вы хотите присоединиться:

Заменить запрос

@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}]. Что я там не так делаю?

Sinan Samet 19.05.2018 20:03

Сообщите мне объект Exams, вы ссылаетесь на неправильное условие where

Mạnh Quyết Nguyễn 19.05.2018 20:07

Я также добавил объект экзаменов

Sinan Samet 19.05.2018 20:08

Попробуйте мой отредактированный ответ. Но, кстати, вы выполнили левое соединение без каких-либо условий для класса User, оно все равно вернет всех пользователей, несмотря ни на что. Вы хотите внутреннего соединения?

Mạnh Quyết Nguyễn 19.05.2018 20:10

Мне нужны все пользователи с готовыми экзаменами независимо от того, есть они у них или нет. Я попробовал ваш запрос, но он все равно дает тот же результат.

Sinan Samet 19.05.2018 20:12

Если вы просто хотите это сделать, просто используйте метод получения ваших сущностей User: user.getFinishedExam(), потому что ваши сущности отображаются

Mạnh Quyết Nguyễn 19.05.2018 20:14

Прошу прощения за свою глупость. Я только что определил метод getFinishedExam (), но где мне его использовать? в контроллере вместо findAll ()?

Sinan Samet 19.05.2018 20:25

Да, сделай это. Он уже сопоставлен и получен (через FetchType.EAGER)

Mạnh Quyết Nguyễn 19.05.2018 20:27

Но я не могу получить доступ к getFinishedExam() через IUserRepository. Это расширение от CrudRepository.

Sinan Samet 19.05.2018 20:30

Чувак. Вы должны сначала изучить базовые вещи, прежде чем погрузиться в программирование без каких-либо знаний. В этом случае вы делаете return userRepository.getAllWithExams();. Ваш finishedExam также будет загружен в ваш список пользователей. Если вы хотите получить доступ к finishedExam пользователя, используйте метод getter.

Mạnh Quyết Nguyễn 19.05.2018 20:32

Возможно, я забыл упомянуть об этом, но мне просто нужно, чтобы это было добавлено в API, когда я обращаюсь к /allUsersWithExams вместе с пользователями. Он в режиме EAGER, так что он должен просто появиться, верно? Извини, я не совсем слежу за тобой

Sinan Samet 19.05.2018 20:39

Да. Вам не нужен специальный метод. Просто верните userRepository.findAll() и получите все необходимое

Mạnh Quyết Nguyễn 19.05.2018 20:41

Да, но это не так. Это просто дает мне всех пользователей, что проблема

Sinan Samet 19.05.2018 20:42

используйте метод findAll()

Mạnh Quyết Nguyễn 19.05.2018 20:45

Да. /user/all использует userRepository.findAll (), но не содержит таблицу finishedExams

Sinan Samet 19.05.2018 20:48

После создания методов получения и установки, игнорирования конфликтующих столбцов и перезапуска приложения оно начало работать. Был долгий день, и все начало сбивать с толку.

Sinan Samet 20.05.2018 00:11

I can put whatever I want in the ON clause but nothing changes.

Конечно ничего не меняется. Вы выполняете левое соединение в отношении 1: 1, выбирая (только) левый объект и не устанавливая никаких критериев фильтрации для этого объекта. Критерии соединения (да и само соединение) не имеют значения: ваш запрос эквивалентен SELECT u FROM User u.

Возможно, вы хотели вместо этого выполнить внутреннее соединение?

Мне нужны все пользователи с готовыми экзаменами независимо от того, есть они у них или нет.

Sinan Samet 19.05.2018 20:09

Поскольку User.finishedExam - это сопоставленная связь, вам не нужно выполнять явное соединение для получения данных экзамена. Просто выберите все User и выполните обычную навигацию по взаимосвязи. Поскольку вы объявили связь с FetchType.EAGER, вам даже не нужно беспокоиться об отсоединении сущностей перед такой навигацией.

John Bollinger 19.05.2018 20:12

Я не понимаю, что вы имеете в виду. Если вы имеете в виду, что я должен пройти userRepository.findAll();, это просто дает мне всех пользователей без экзаменов. Однако они связаны.

Sinan Samet 19.05.2018 20:15

@SinanSamet, получив сущности User, вы сможете просто вызвать user.getFinishedExam() для получения связанной сущности FinishedExam, если таковая имеется. Конечно, было бы полезно, если бы вы на самом деле при условии такой геттер (и сеттер тоже). Непонятно, почему вы объявляете свойство, но не имеете доступа к нему.

John Bollinger 19.05.2018 20:18

Я добавил получатель в модель User, но, как я уже сказал в другом ответе, использование userRepository.findAll () возвращает мне только пользователей, но не их таблицу finishedExams.

Sinan Samet 19.05.2018 21:06

Другие вопросы по теме