首页 > 解决方案 > 恢复具有相关实体的实体列表,同时使用 JPQL 或条件 API 省略某些字段

问题描述

我有三个实体:A,B,C

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor

@Entity
public class A {

    private long id;

    private String secret;

    @Builder.Default
    @Valid
    @OneToMany(mappedBy = "a", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @Fetch(value = FetchMode.SUBSELECT)
    private List<B> bList = new LinkedList<>();

}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor

@Entity
public class B {

    @JoinColumn
    private A a;

    private long id;

    private String secret;

    @Builder.Default
    @Valid
    @OneToMany(mappedBy = "b", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @Fetch(value = FetchMode.SUBSELECT)
    private List<C> cList = new LinkedList<>();

}


@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor

@Entity
public class C {

    @JoinColumn
    private B b;

    private long id;

    private String secret;
}

我想从数据库中恢复值,除了A 的 id 属于 id 列表的“秘密”。我不希望从 DB 请求 A、B 或 C 的秘密。(实际上数据要复杂得多,我不希望从数据库中获取太多时间的字段)。

我一直在尝试使用 JPQL 或 Criteria API 创建这样的查询,但没有成功,我什至无法获得没有秘密的 B 列表。

例如在 JPQL 中:

        Query query = entityManager.createQuery
                ("SELECT a  " +
                        "FROM A a where a.id in :aIds");
        query.setParameter("aIds", aIds);

这将起作用,但不幸的是它还要求 A、B 和 C 的秘密。

我想要的是类似的东西(这段代码显然不起作用):

        Query query = entityManager.createQuery
                ("SELECT a.id, a.bList.id, a.bList.cList.id" +
                        "FROM A a where a.id in :aIds");
        query.setParameter("aIds", aIds);

我无法更改实体(除了添加新的构造函数或方法),因为它们在其他地方和其他查询中使用。

这甚至可能吗?

标签: javajpqlcriteria-api

解决方案


您可以使用您需要的字段创建dto类并填充它。问题是数据库查询只能返回纯结果。持久性提供者可以将其转换为实体。至于dto你必须自己解决问题。

您可以得到List<Object[]>查询结果

select a.id, b.id, c.id 
from A a join a.bList b join b.cList c 
where a.id in(:aIds)

然后你应该将查询结果转换为 dto


推荐阅读