2017-03-06 82 views
0

Link.java預先抓取子父加載彈簧數據JPA時

@Entity 
@Table(name = "LINK") 
@AttributeOverride(name="id", [email protected](name="LINK_ID")) 
public class Link extends AbstractAuditableEntity<Integer> { 

    /** 
    * 
    */ 
    private static final long serialVersionUID = 3825555385014396995L; 

    @Column(name="NAME") 
    private String name; 

    @Column(name="UI_SREF") 
    private String uiSref; 

    @ManyToOne 
    @JoinColumn(name="PARENT_LINK_ID") 
    private Link parentLink; 

    @OneToMany(mappedBy="parentLink", fetch = FetchType.EAGER) 
    private List<Link> childLinks; 

    /** 
    * @return the name 
    */ 
    public String getName() { 
     return name; 
    } 

    /** 
    * @param name the name to set 
    */ 
    public void setName(String name) { 
     this.name = name; 
    } 

    /** 
    * @return the uiSref 
    */ 
    public String getUiSref() { 
     return uiSref; 
    } 

    /** 
    * @param uiSref the uiSref to set 
    */ 
    public void setUiSref(String uiSref) { 
     this.uiSref = uiSref; 
    } 

    /** 
    * @return the parentLink 
    */ 
    public Link getParentLink() { 
     return parentLink; 
    } 

    /** 
    * @param parentLink the parentLink to set 
    */ 
    public void setParentLink(Link parentLink) { 
     this.parentLink = parentLink; 
    } 

    /** 
    * @return the childLinks 
    */ 
    public List<Link> getChildLinks() { 
     return childLinks; 
    } 

    /** 
    * @param childLinks the childLinks to set 
    */ 
    public void setChildLinks(List<Link> childLinks) { 
     this.childLinks = childLinks; 
    } 


} 

LinkRepository的.java

public interface LinkRepository extends BaseRepository<Integer, Link> { 

    @Query("select distinct p from Link l JOIN fetch l.parentLink p where l.id in (select lar.link.id from LinkAccessRole lar where lar.accessRoleLu in ?1) and p.id in (select lar.link.id from LinkAccessRole lar where lar.accessRoleLu in ?1)") 
    public List<Link> getNavigationByaccessRoleLuList(List<AccessRoleLu> accessRoleLu); 
} 

Link_Table Link_Access_Role Table

生成查詢:

SELECT DISTINCT t0.LINK_ID, t0.CREATED_BY_ID, t0.CREATED_DATE, t0.LAST_MODIFIED_BY_ID, t0.LAST_MODIFIED_DATE, t0.NAME, t0.UI_SREF, t0.PARENT_LINK_ID FROM LINK t0, LINK t1 WHERE ((t1.LINK_ID IN (SELECT t2.LINK_ID FROM LINK_ACCESS_ROLE t3, LINK t2 WHERE ((t3.ACCESS_ROLE_ID IN (?,?)) AND (t2.LINK_ID = t3.LINK_ID))) AND t0.LINK_ID IN (SELECT t4.LINK_ID FROM LINK_ACCESS_ROLE t5, LINK t4 WHERE ((t5.ACCESS_ROLE_ID IN (?,?)) AND (t4.LINK_ID = t5.LINK_ID)))) AND (t0.LINK_ID = t1.PARENT_LINK_ID)) 
     bind => [4 parameters bound] 
    SELECT LINK_ID, CREATED_BY_ID, CREATED_DATE, LAST_MODIFIED_BY_ID, LAST_MODIFIED_DATE, NAME, UI_SREF, PARENT_LINK_ID FROM LINK WHERE (PARENT_LINK_ID = ?) 
     bind => [1 parameter bound] 
    SELECT LINK_ID, CREATED_BY_ID, CREATED_DATE, LAST_MODIFIED_BY_ID, LAST_MODIFIED_DATE, NAME, UI_SREF, PARENT_LINK_ID FROM LINK WHERE (PARENT_LINK_ID = ?) 
     bind => [1 parameter bound] 

我爲每個與獲取的父項相關的子項獲取一個查詢無論它是否具有訪問角色。

我想取得父母及其子女有訪問角色不是所有與該父母相關的子女。

+0

您有fetch = FetchType.EAGER。你認爲這是爲了什麼?它告訴JPA每次加載鏈接時,都必須加載它的子節點。 –

+0

沒錯。我如何根據他們的訪問角色來獲取他們,因爲我正在嘗試這樣做。 –

回答

0

基於標準,您可以獲取父實體並使其中一個集合中的某個集合填充其中一個集合的唯一方法是使用Hibernate的專有過濾器。

我不確定其他JPA提供商是否提供某種專有解決方案,但JPA本身不提供此直接。

您首先需要使用@FilterDef註冊過濾器定義,然後您需要使用集合屬性上的@Filter引用過濾器的定義。

這裏最難的部分就是您不能依賴Spring數據的@Query或其存儲庫實現生成過程來提供幫助。您需要使用真正的實現,以便您可以在之前手動啓用此休眠篩選器,以查詢父實體。

Filter filter = session.enableFilter("link-with-restrictions-by-roles"); 
filter.setParameter("roles", yourRolesList); 
return session.createQuery(...).getResultList(); 

該文檔描述了使用@Filter並詳細@FilterDef。你也可以找到我的另一篇文章,我稍微提供一些實施細節here