如何在不触及目标表的情况下从JPA ManyToOne映射中检索外键? [英] How can I retrieve the foreign key from a JPA ManyToOne mapping without hitting the target table?

查看:165
本文介绍了如何在不触及目标表的情况下从JPA ManyToOne映射中检索外键?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下两个用于构建图形的带注释的类:

I have the following two annotated classes that I use to build a graph:

@Entity
@Table(name = "Edge")
public class Edge
{
    /* some code omitted for brevity */

    @ManyToOne
    @JoinColumn(name = "ixNodeFrom", nullable = false)
    private Node         _nodFrom;

    @ManyToOne
    @JoinColumn(name = "ixNodeTo", nullable = false)
    private Node         _nodTo;

    /* some code omitted for brevity */
}

@Entity
@Table(name = "Node")
public class Node
{
    /* some code omitted for brevity */

    @OneToMany(mappedBy = "_nodTo")
    private Set<Edge>    _rgInbound;

    @OneToMany(mappedBy = "_nodFrom")
    private Set<Edge>    _rgOutbound;

    /* some code omitted for brevity */
}

现在,当我构建图形时,我发出两个查询来从任一个表中获取所有行并设置子/父引用,为此我需要存储在 Edge table。

Now, when I build the graph, I issue two queries to fetch all rows from either table and set up the child / parent references, for which I need the ids stored in the Edge table.

因为我在JPA中定义了两个表之间的关系,所以访问edge对象以获取两个节点的id会触发每个边缘两个SQL语句,当JPA提供程序 lazily *加载关联的节点时。由于我已经有了节点对象,并且已经从边缘表加载了id,因此我想跳过这些查询,因为它们需要花费很长时间来处理较大的图形。

Because I have defined the relation between the two tables in JPA, accessing the edge object to get the two nodes' ids triggers two SQL statements per edge, when the JPA provider lazily * loads the associated nodes. Since I already have the node objects, and the ids have already been loaded from the edge table, I want to skip those queries, as they take an awfully long time for larger graphs.

我尝试将这些行添加到 Edge 类中,但是我的JPA提供程序要求我将一个映射设置为只读,我似乎无法找到如何做到这一点:

I tried adding these lines to the Edge class, but then my JPA provider wants me to make one mapping read-only, and I can't seem to find a way how to do that:

@Column(name = "ixNodeTo")
private long _ixNodeTo;

@Column(name = "ixNodeFrom")
private long _ixNodeFrom;

我正在使用Eclipselink和MySQL,如果重要的话。

I'm using Eclipselink and MySQL, if it matters.

** @ManyToOne 的默认行为实际上是急切加载,请参阅 Pascal的答案 *

**The default behaviour for @ManyToOne actually is eager loading, see Pascal's answer*

推荐答案

I得到了三个同样有帮助的好答案,现在没有人通过公众投票渗透到最高层,所以我将它们合并在一起作为一个全面的答案:

您可以通过更改查询立即加载整个图表,从而让JPA提供商有机会意识到它已经有了内存中的所有内容,无需返回数据库:

You can load the whole graph at once by changing the query, thereby giving the JPA provider a chance to realize that it already has everything in memory and doesn't need to go back to the DB:

List<Node> nodes = em.createQuery(
        "SELECT DISTINCT n FROM Node n LEFT JOIN FETCH n._rgOutbound")
        .getResultList();

(通过 axtavt

如问题中所述,将FK加载到自己的字段中,如果JPA提供者要求将字段声明为只读字段,那么它也将起作用,如下所示:

Loading the FKs into their own fields, as described in the question, will also work if, as the JPA provider is demanding, the fields are declared to be readonly, which is done like this:

@Column(name = "ixNodeTo", insertable = false, updatable = false)

(通过 bravocharlie

如果您使用属性访问而不是 field access ,JPA提供程序也有机会意识到它已经拥有FK并且不需要获取引用的对象。简而言之,属性访问意味着您将JPA注释放在getter上,从而承诺您的getter不会去的JPA提供者并访问该对象的其余部分。 此问题中的更多详细信息。这适用于Hibernate,对于Eclipselink,它将起作用(在原始答案中假定,由我实验确认)并启用编织。 (通过 Pascal Thivent

If you are using property access instead of field access, the JPA provider also gets a chance to realize it already has the FK and doesn't need to fetch the referenced object. In short, property access means that you put the JPA annotations on the getter, thereby "promising" the JPA provider that your getter won't go and access the rest of the object. More details in this question. This will work for Hibernate, and for Eclipselink, it will work (assumed in the original answer, experimentally confirmed by me) with weaving enabled. (via Pascal Thivent)

此外,正如 Pascal在答案中指出的那样 @ManyToOne ,与我的原始帖子相反,不是延迟加载,而是默认加载,并且更改它也需要编织。

Additionally, as Pascal points out in his answer, @ManyToOne, contrary to my original post, is not lazy-loading, but eager-loading by default, and changing that will require weaving as well.

这篇关于如何在不触及目标表的情况下从JPA ManyToOne映射中检索外键?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆