如何在单个查询中检索嵌套的 JPA 实体

发布于 2024-11-24 05:29:47 字数 948 浏览 0 评论 0原文

我正在尝试使用 eclipselink JPA 检索实体,并且正在寻找一种方法来减少为检索单个实体而运行的查询数量。我相信我应该使用 @JoinFetch 注释来检索与主实体相同的查询中的子实体。这对于单级别的连接来说效果很好,但对于多级别的连接却不起作用。

在下面的示例中,EntityA 包含 EntityB 的集合,EntityB 又包含 EntityC。当我检索 EntityA 时,我希望单个查询返回所有 3 组实体数据。实际上,它生成 2 个查询,其中 1 个连接 EntityA 和 EntityB,然后是一个单独的查询连接 EntityB 和 EntityC。

是否可以将其合并到一个查询中?

class EntityA {
    @OneToMany(mappedBy = "entityALink", fetch = FetchType.EAGER)
    @JoinFetch
    private Collection<EntityB> entityBs;
}

class EntityB {
    @JoinColumn(name = "X", referencedColumnName = "Y")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private EntityA entityALink;

    @JoinColumn(name = "A", referencedColumnName = "B")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinFetch
    private EntityC entityCLink;
}

class EntityC {

    @Id
    @Basic(optional = false)
    @Column(name = "SomeColumn")
    private String someField
}

I am trying to retrieve entities using eclipselink JPA and am looking for a way to reduce the number of queries run to retrieve a single entity. I believe I should be using the @JoinFetch annotation to retrieve sub-entities in the same query as the main entity. This works fine for a single level of join, but not for multiple levels.

In the example below, EntityA contains a collection of EntityB which contains an EntityC. When I retrieve EntityA, I want a single query to return all 3 sets of entity data. In reality it generates 2 queries, 1 joining EntityA and EntityB and then a separate query joining EntityB and EntityC.

Is it possible to combine this into one query?

class EntityA {
    @OneToMany(mappedBy = "entityALink", fetch = FetchType.EAGER)
    @JoinFetch
    private Collection<EntityB> entityBs;
}

class EntityB {
    @JoinColumn(name = "X", referencedColumnName = "Y")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private EntityA entityALink;

    @JoinColumn(name = "A", referencedColumnName = "B")
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    @JoinFetch
    private EntityC entityCLink;
}

class EntityC {

    @Id
    @Basic(optional = false)
    @Column(name = "SomeColumn")
    private String someField
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

饮湿 2024-12-01 05:29:47

如果您需要减少查询数量,您可以使用延迟初始化 - FetchType.LAZY 而不是 FetchType.EAGER - 这样 jpa 在需要时从数据库获取数据。但您必须记住,当实体与管理器断开连接时,这不起作用。因此,如果您以序列化形式将此实体发送到其他服务器(例如在多级应用程序中),则必须再次将此实体与管理器连接。如果您的应用程序在一台服务器上运行,那么您就不会遇到此问题。

总结并不是您问题的确切答案,但可能有助于优化此代码。

您问题的确切答案:
您可以使用命名查询,但查询会解析为 sql 本机查询,并且您不确定这是否按您想要的方式工作。但也许您可以使用本机查询方法?

em.createNativeQuery("SELECT ... your queries") 

为此,请阅读有关使用 @SqlResultSetMapping 注解配置结果实体类的内容...

If you need reduce number of queries, you may using lazy initialization - FetchType.LAZY instead of FetchType.EAGER - in this way jpa get data from databases when need. But you must remember, this is not working when entity is disconnected from manager. So if you send this entity to other servers in serialize the form (ex. in multi-level application) you must again connected this entity with manager. If you application runs in one server, then you don't have this problem.

Summing up is not the exact answer to your question, but maybe helpful for optimize this code.

Exact answer for you question:
You may using named queries, but then query is parse to sql native query, and you don't sure that this working as you want. But maybe you may using native query method?

em.createNativeQuery("SELECT ... your queries") 

For this purpose, please read about using @SqlResultSetMapping annotation to configure result entity class...

葮薆情 2024-12-01 05:29:47

首先编写一个查询来获取EntityA。

EntityA entity = <your Query> ;

然后调用

Collection<EntityB> entityB = entity.getEntityBs();
for(EntityB eachB : entityB){

    EntityC entityCLink = eachB.getEntityCLink();
}

注意:创建setter &每个实体中的吸气剂。

First write a query to get EntityA.

EntityA entity = <your Query> ;

then call

Collection<EntityB> entityB = entity.getEntityBs();
for(EntityB eachB : entityB){

    EntityC entityCLink = eachB.getEntityCLink();
}

Note: Create setter & getters in each entity.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文