2017-03-06 83 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