【问题标题】:JPA Projection: select only some items and an entire entity of @OneToMany relationshipJPA投影:仅选择@OneToMany关系的一些项目和整个实体
【发布时间】:2020-09-05 19:33:36
【问题描述】:

我有这两个实体:

@Entity
@Table(name = "ORGANIZATION")
public class Organization implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy = "organization", fetch = FetchType.LAZY)
    private Set<OrganizationMeta> metas;

    public Organization() {
        super();
    }

    public Organization(Long id, String name, Set<OrganizationMeta> metas) {
        super();
        this.id = id;
        this.name = name;
        this.metas = metas;
    }

    // ... others fields ... getters and setters
}

@Entity
@Table(name = "ORGANIZATION_META")
public class OrganizationMeta implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Enumerated(EnumType.STRING)
    @Column(name = "meta_key", length = 200, nullable = false)
    private OrganizationMetaKeyEnum metaKey;

    private String metaValue;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(nullable = false)
    private Organization organization;

    // ... getters and setters ...
}

所以一个组织可以有一个或多个OrganizationMeta,这是一个简单的情况。

ORGANIZATION_META 表中有外键,所以它是关系的所有者。

在组织实体中,我有一组由 @OneToMany 加载的元数据。

我想写一个使用投影的查询,因为我只想要组织实体的一些字段,但同时我想要整个组织元实体。

这是 JPQL 查询,但我总是有不同的错误

@Query("select new net.feed.feedentity.domain.organization.Organization(organization.id, organization.name, organization.metas) from Organization organization left join fetch organization.metas where organization.id = ?1")

似乎不可能在投影中选择@OneToMany 字段的集合或列表。

可以这样做吗?有人遇到过这个问题吗?

【问题讨论】:

  • 有什么不同的错误?
  • 我遇到了同样的问题,我可以使用基于接口的投影来实现它(需要为两个类创建一个单独的投影接口)。
  • @Vishnu,下面有两种解决方案,一种来自我,另一种来自我。

标签: hibernate jpa spring-data-jpa hql jpql


【解决方案1】:

我建议您通过对组织实体执行封闭投影技术来接收数据,因为您需要的只是组织类的一个子集。

在这种情况下;您需要定义一个投影接口,该接口需要包含您感兴趣的属性的 getter 方法。这是你必须遵守的规则。名称应匹配。

界面将如下所示:

public interface OrganizationView {
    String getId();
    String getName();
    Set<OrganizationMeta> getMetas();
}

你可以给你的界面起任何名字,我用的是OrganizationView

您将使用此接口作为返回类型。您可以在组织存储库中定义方法,如下所示。

public interface OrganizationRepository extends JpaRepository<Organization, Long> {

    @Query("select organization.id, organization.name, organization.metas from Organization organization left join fetch organization.metas where organization.id = ?1")
    List<OrganizationView> findSubsetById(Long id);
}

最后调用OrganizationView接口的方法获取数据。

编辑:你可以看看这个page关于用样本投影的解释。

【讨论】:

  • 我知道这个技巧,但我没有想过。我会尝试。与此同时,我找到了另一个解决方案。
  • @AndreaBevilacqua 你找到了什么解决方案?
猜你喜欢
  • 1970-01-01
  • 2020-05-23
  • 2021-12-21
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
相关资源
最近更新 更多