Контекст: у меня есть две таблицы: анкета и раздел вопросов. Анкета может иметь много разделов вопросов. Анкеты и разделы вопросов имеют начальную и конечную даты, чтобы определить, являются ли они активными записями.
Вот мои сущности, как написано:
@Entity
@Data
public class Questionnaire {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private Date startDate;
private Date endDate;
private String description;
@OneToMany(cascade = CascadeType.All,
fetch = FetchType.LAZY,
mappedBy = "questionnaire")
@JsonManagedReference
private List<QuestionSection> questionSections = new ArrayList<QuestionSection>();
}
@Entity
@Data
public class QuestionSection {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
private String name;
private String description;
private int sectionLevel;
private Date startDate;
private Date endDate;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "QUESTIONNAIRE_ID", nullable = false)
@JsonBackReference
private Questionnaire questionnaire;
}
Вот мое хранилище данных Spring с одним объявленным методом:
public interface QuestionnaireRepository extends JpaRepository<Questionnaire, UUID> {
Questionnaire findByNameAndEndDateIsNull(String name);
// Previous goal query, but worked all the way back to the above simple query
// Questionnaire findByIdAndQuestionSectionsEndDateIsNull(UUID id);
}
Приведенный выше производный запрос генерирует два запроса, показанных ниже:
-- For brevity
select questionnaire.id as id
questionnaire.description as description
questionnaire.end_date as end_date
questionnaire.start_date as start_date
from questionnaire
where questionnaire.name='Foo' and (questionnaire.end_date is null)
select questionsection.questionnaire_id as questionnaire id
...rest of fields here...
from question_section
where questionsection.questionnaire_id = id from above query
Затем Spring Data или Hibernate объединяет эти два вышеупомянутых запроса в один объект данных, представляющий объект вопросника, и возвращает его.
Моя проблема с этим заключается в том, что я ожидал, что Один запрос будет выполнен с соединением между двумя таблицами, а не двумя, и затем объединит результаты в памяти. У меня довольно большой опыт работы со Spring Data и ORM в целом, и я не смог найти никакой документации о том, почему это происходит. Честно говоря, мне было бы все равно, за исключением того, что мое первоначальное намерение состояло в том, чтобы запрашивать у родительской сущности и «отфильтровывать» дочерние элементы, у которых есть даты окончания (неактивные). Этот производный запрос (закомментированный выше) демонстрировал то же поведение, что в итоге привело к тому, что был возвращен набор данных, содержащий разделы с конечным датированным вопросом.
Я знаю, что есть 100 других способов, которыми я мог бы решить эту проблему (и это хорошо), так что на данный момент это больше интересует меня с точки зрения образования, если у кого-то есть понимание этого поведения. Я мог упустить что-то действительно простое.