簡體   English   中英

加載多對多關系並映射到實體

[英]Load many-to-many relationship and map to entity

我對 Spring Boot/Hibernate 開發還很陌生,這是我的第一個大項目。

我有一個應用程序使用 Spring Boot、Hibernate 和 Hibernate Envers 來審計一些實體。 Hibernate Envers 設置為使用 ValidityAuditStrategy。 由於 Hibernate Envers 不支持開箱即用的急切加載對多關系,我試圖找到一種方法來執行單個查詢並檢索我需要的所有數據,以避免 N+1 查詢問題,目前,正在扼殺我的表現:在我們的開發環境中需要將近 2 分鍾才能完全加載我們需要的具有所需關系的實體。

由於我需要檢索經過審核的版本,因此我無法像在應用程序的其他部分中使用的那樣利用 EntityGraph(至少在我的理解中)。

我需要解決的一種情況有 4 個實體ParameterFormulaValueVariable ,它們像這樣相關(僅顯示相關部分, ValueVariable是實體,此處未列出)

@Entity
public class Parameter {
  @OneToOne(fetch = FetchType.LAZY, optional = false)
  @JoinColumn(name = "formula_id", referencedColumnName = "id", nullable = false)
  private Formula formula;
}

@Entity
public class Formula {
  @ManyToOne(optional = false)
  @JoinColumn(name = "tag_id")
  private Value tag;

  @ManyToMany
  @JoinTable(
      name = "Formulas_Variables",
      joinColumns = @JoinColumn(name = "formula_id"),
      inverseJoinColumns = @JoinColumn(name = "variable_id"))
  private Set<Variable> variables = new HashSet<>();
}

我試圖做的是創建一個自定義查詢和使用結果映射@NamedNativeQuery@SqlResultSetMapping但是,即使休眠創造之間的關系FormulaValue正確,它不是建立在數組variables場。 我使用的查詢和映射如下:

@SqlResultSetMapping(name = "Parameter.findAllByRevisionMapping", entities = {
    @EntityResult(entityClass = Parameter.class, fields = {
        @FieldResult(name = "id", column = "id"),
        @FieldResult(name = "formula", column = "formula_id")
    }),
    @EntityResult(entityClass = Formula.class, fields = {
        @FieldResult(name = "id", column = "formulaId"),
        @FieldResult(name = "tag", column = "tag_id"),
        @FieldResult(name = "variables", column = "variable_id")
    }),
    @EntityResult(entityClass = DomainValue.class, fields = {
        @FieldResult(name = "id", column = "tag_id")
    }),
    @EntityResult(entityClass = Variable.class, fields = {
        @FieldResult(name = "id", column = "variableId")
    })
})
@NamedNativeQuery(name = "Parameter.findAllByRevision", query = "SELECT om_c_p_aud.id,\n"
    + "       f_aud.id AS formulaId,\n"
    + "       dv_aud.id AS tag_id,\n"
    + "       fv_aud.formula_id AS formula_id,\n"
    + "       v_aud.id AS variable_id,\n"
    + "       v_aud.id AS variableId\n"
    + "FROM Parameters_AUD om_c_p_aud\n"
    + "         LEFT OUTER JOIN Formulas_AUD f_aud\n"
    + "                    ON f_aud.id = om_c_p_aud.formula_id AND f_aud.REV <= ?1 AND\n"
    + "                       f_aud.REVTYPE <> 2 AND (f_aud.REVEND > ?1 OR\n"
    + "                                               f_aud.REVEND IS NULL)\n"
    + "         LEFT OUTER JOIN Values_AUD dv_aud\n"
    + "                    ON dv_aud.id = f_aud.tag_id AND dv_aud.REV <= ?1 AND\n"
    + "                       dv_aud.REVTYPE <> 2 AND (dv_aud.REVEND > ?1 OR\n"
    + "                                                dv_aud.REVEND IS NULL)\n"
    + "         LEFT OUTER JOIN Formulas_Variables_AUD fv_aud\n"
    + "                    ON fv_aud.formula_id = f_aud.id AND fv_aud.REV <= ?1 AND\n"
    + "                       fv_aud.REVTYPE <> 2 AND (fv_aud.REVEND > ?1 OR\n"
    + "                                                fv_aud.REVEND IS NULL)\n"
    + "         LEFT OUTER JOIN Variables_AUD v_aud\n"
    + "                    ON v_aud.id = fv_aud.variable_id AND v_aud.REV <= ?1 AND\n"
    + "                       v_aud.REVTYPE <> 2 AND (v_aud.REVEND > ?1 OR\n"
    + "                                               v_aud.REVEND IS NULL)\n"
    + "WHERE om_c_p_aud.REV <= ?1\n"
    + "  AND om_c_p_aud.REVTYPE <> 2\n"
    + "  AND (om_c_p_aud.REVEND > ?1 OR\n"
    + "       om_c_p_aud.REVEND IS NULL)", resultSetMapping = "Parameter.findAllByRevisionMapping")

直接在數據庫上執行查詢的結果示例如下: 查詢示例結果

我在調用findAllByRevision查詢時收到的 json 對象的結果數組是這樣的

[
   {
      "id":1,
      "formula":{
         "id":52,
         "tag":{
            "id":20
         },
         "variables":null
      }
   },
   {
      "id":2,
      "formula":{
         "id":88,
         "tag":{
            "id":24
         },
         "variables":null
      }
   },
   {
      "id":2,
      "formula":{
         "id":88,
         "tag":{
            "id":24
         },
         "variables":null
      }
   },
   {
      "id":2,
      "formula":{
         "id":88,
         "tag":{
            "id":24
         },
         "variables":null
      }
   },
   {
      "id":2,
      "formula":{
         "id":88,
         "tag":{
            "id":24
         },
         "variables":null
      }
   },
   {
      "id":2,
      "formula":{
         "id":88,
         "tag":{
            "id":24
         },
         "variables":null
      }
   },
   {
      "id":2,
      "formula":{
         "id":88,
         "tag":{
            "id":24
         },
         "variables":null
      }
   }
]

而我期望的是

[
   {
      "id":1,
      "formula":{
         "id":52,
         "tag":{
            "id":20
         },
         "variables":[
            {
               "id":4
            }
         ]
      }
   },
   {
      "id":2,
      "formula":{
         "id":88,
         "tag":{
            "id":24
         },
         "variables":[
            {
               "id":3
            },
            {
               "id":23
            },
            {
               "id":33
            },
            {
               "id":34
            },
            {
               "id":35
            },
            {
               "id":52
            }
         ]
      }
   }
]

有誰知道為什么它不創建公式 <-> 變量關系? 在類似情況下使用 EntityGraph 時,我嘗試檢查 Hibernate 創建的查詢,在我看來,它與上面顯示的查詢相同。 我無法檢查在這種情況下使用的映射(再次以我的理解)。

您應該能夠使用 HQL 為審計關聯指定連接提取。 被審計的實體就像一個普通的實體。 實體名稱通常以“_AUD”為后綴,因此如果您想查詢Parameters的審計信息,您可以查詢Parameters_AUD ,例如:

SELECT p
FROM Parameters_AUD p
LEFT JOIN FETCH p.values
LEFT JOIN FETCH p.variables

暫無
暫無

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

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