(1) JPA N+1問題解決 方案 查詢效率優化

問題背景:

在設計一個樹形結構的實體中用到了多對一,一對多的映射關係,在加載其關聯對象的時候,爲了性能考慮,很自然的想到了懶加載。

也因此遇到了N+1的典型問題 : 通常1的這方,通過1條SQL查找得到1個對象,而JPA基於Hibernate,fetch策略默認爲select(並非聯表查詢),由於關聯的存在 ,又需要將這個對象關聯的集合取出,集合數量是N,則要發出N條SQL,於是本來的1條聯表查詢SQL可解決的問題變成了N+1條SQL

 

JPA 2.1推出來的@EntityGraph、@NamedEntityGraph用來提高查詢效率,很好地解決了N+1條SQL的問題。兩者需要配合起來使用,缺一不可。@NamedEntityGraph配置在@Entity上面,而@EntityGraph配置在Repository的查詢方法上面.通過聯表查詢進行解決。

解決的方法如下 : 

Demo 如下:

  1 . 首先在實體上面註解@NamedEntityGraph,指明name供查詢方法使用,attributeNodes 指明被標註爲懶加載的屬性節點




@Entity
@Getter
@Setter
@Table(name = "ORG_AGENCY")
@NamedEntityGraph(name = "Agency.Graph", attributeNodes = {@NamedAttributeNode("region"), @NamedAttributeNode("parent"),@NamedAttributeNode("mofDep"),@NamedAttributeNode("unit")})
public class Agency extends BaseEntity {

    
   
    @Field
    @Column(nullable = false)
    @ApiModelProperty(value = "編碼", required = true)
    private String code; 

    @Field
    @Column(nullable = false)
    @ApiModelProperty(value = "名稱", required = true)
    private String name; 

    
    @ApiModelProperty(value = "是否啓用")
    private Boolean enabled; // 是否啓用

    
    @ApiModelProperty(value = "級次")
    private Integer levelNum;

    
    @ApiModelProperty(value = "內部編碼")
    private String innerCode;

    
    @ApiModelProperty(value = "是否末級")
    private Boolean leafNode;

   
    @ApiModelProperty(value = "是否允許增加下級")
    private Boolean expandable;

    
    
    @ApiModelProperty(value = "所屬區劃")
    @ManyToOne(fetch = FetchType.LAZY)
    private Region region;

   
   

    @ManyToOne(fetch = FetchType.LAZY)
    @ApiModelProperty(value = "上級")
    private Agency parent;



   
    @ApiModelProperty(value = "年度")
    private String year;

 

  
    

    
    @ApiModelProperty(value = "業務處室")
    @ManyToOne(fetch = FetchType.LAZY)
    private MOFDep mofDep;

   
    @ApiModelProperty(value = "來源單位")
    @ManyToOne(fetch = FetchType.LAZY)
    private Organization unit;

   
}

2 . 在訪問的dao的查詢方法上面註解@EntityGraph,value屬性值爲@NamedEntityGraph的name屬性值,如 AgencyRepository : 


public interface AgencyRepository extends GenericRepository<Agency> {

    @QueryHints(value = {@QueryHint(name = "org.hibernate.cacheable", value = "true")})
    @EntityGraph(value = "Agency.Graph", type = EntityGraph.EntityGraphType.FETCH)
    List<Agency> findAll(Predicate predicate, Sort sort);

   
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章