簡體   English   中英

Spring Data/Hibernate 生成兩個查詢而不是一個 JOIN

[英]Spring Data/Hibernate Generates two queries instead of a JOIN

上下文:我有兩個表:問卷和問題部分。 一個問卷可以有許多問題部分。 問卷和問題部分都有開始和結束日期來確定它們是否是活動記錄。

以下是我所寫的實體:

@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 將上述兩個查詢組合成一個代表問卷對象的數據對象並返回。

我的問題是,我希望一個查詢在兩個表之間運行一個連接,而不是兩個,然后將結果合並到內存中。 總的來說,我對 Spring Data 和 ORM 非常有經驗,並且無法找到任何關於為什么會發生這種情況的文檔。 老實說,除了我的初衷是查詢父實體並“過濾”出具有結束日期(未激活)的子實體之外,我並不在乎。 這個派生查詢(上面注釋掉)表現出相同的行為,最終導致返回的數據集包含結束日期的問題部分。 我知道還有 100 種其他方法可以解決這個問題(這很好)所以如果有人對這種行為有任何了解,那么這對我來說更具有教育意義。 我可能會遺漏一些非常簡單的東西。

您應該能夠使用 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);
}
public interface QuestionnaireRepository extends JpaRepository<Questionnaire, UUID> {
  @EntityGraph(attributePaths = { "questionSections" })
  Questionnaire findByNameAndEndDateIsNull(String name);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM