在加载父弹簧数据jpa时急切地获取子项

时间:2017-03-06 08:44:11

标签: spring jpa spring-data spring-data-jpa jpa-2.1

Link.java

@Entity
@Table(name = "LINK")
@AttributeOverride(name="id", column=@Column(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]

我为与获取的父级相关的每个子项获得一个查询,无论它是否具有访问角色。

我想获取具有访问角色的父母及其子女,而不是所有与该父母相关的孩子。

1 个答案:

答案 0 :(得分:0)

使用Hibernate的专有过滤器,唯一可以获取父实体并使用基于某些条件的条目子集填充其集合的方法。

我不确定其他JPA提供商是否提供了一些专有解决方案,但JPA本身并不直接提供此解决方案。

首先需要使用@FilterDef注册过滤器定义,然后需要使用集合属性上的@Filter来引用过滤器的定义。

这里的难点在于您不能依赖Spring数据的@Query或其存储库实现生成过程来提供帮助。您将需要使用一个真正的实现,以便您可以在查询父实体之前手动启用此hibernate过滤器

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

该文档详细介绍了@Filter@FilterDef的用法。您还可以在我的另一篇文章中找到更多实施细节here