上下文:我有两个表:“问卷”和“问题”部分。问卷可以有多个问题部分。问卷和问题部分都有开始日期和结束日期,以确定它们是否为活动记录。
这是我写的实体:
@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 Data Repository,它具有一个声明的方法:
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将上述两个查询组合成一个代表调查表对象的数据对象,并将其返回。
我的问题是我希望一个查询在两个表(而不是两个)之间使用Join来运行,然后将结果合并到内存中。一般而言,我对Spring Data和ORM相当有经验,因此无法找到任何有关为什么发生这种情况的文档。老实说,除了我的初衷是查询父实体并“过滤”具有结束日期(未激活)的子代,我不在乎。这个派生的查询(上面已注释)表现出相同的行为,最终导致返回包含结束日期的问题部分的数据集。 我知道有100种其他方法可以解决此问题(很好),因此,如果有人对此行为有任何见解,那么这对我而言更具有教育意义。我可能会错过一些非常简单的东西。
答案 0 :(得分:0)
public interface QuestionnaireRepository extends JpaRepository<Questionnaire, UUID> {
@EntityGraph(attributePaths = { "questionSections" })
Questionnaire findByNameAndEndDateIsNull(String name);
}
答案 1 :(得分:0)
您应该能够使用JPA 2.1中引入的“实体图”功能来执行此操作。
https://www.baeldung.com/jpa-entity-graph
Spring Data通过@NamedEntityGraph
和@EntityGraph
批注提供对实体图的支持:
https://www.baeldung.com/spring-data-jpa-named-entity-graphs
所以在您的代码中:
实体:
@Entity
@NamedEntityGraph(name = "Questionnaire.questionSections",
attributeNodes = @NamedAttributeNode("questionSections ")
)
public class Questionnaire{
//...
}
存储库:
public interface QuestionnaireRepository extends JpaRepository<Questionnaire, UUID> {
@NamedEntityGraph("Questionnaire.questionSections")
Questionnaire findByNameAndEndDateIsNull(String name);
}