加载 parent spring 数据时急切获取 child jpa

Eagerly fetch child when loading parent spring data jpa

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;
    }


}

链接库。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]

我为每个 child 获取一个与获取的 parent 相关的查询,无论它是否具有访问角色。

我想获取 parents 及其具有访问权限的 childs 而不是所有与 parent 相关的 childs。

获取父实体并使用基于某些条件 的条目子集填充其中一个集合的唯一方法是使用 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 的用法。您还可以找到我的另一个 post,我在其中提供了更多实现细节 .