如何在不敲击目标表的情况下从JPA ManyToOne映射中检索外键?

Han*_*etz 13 java jpa eclipselink

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

@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 */
}
Run Code Online (Sandbox Code Playgroud)

现在,当我建立图,我发出了两次查询或者从表获取所有行,并成立了父/子引用,为此我需要存储在的ID Edge表.

因为我已经定义JPA中的两个表之间的关系,访问边缘对象来获取两个节点的IDS触发每边两个SQL语句,当JPA提供商懒洋洋*加载相关联的节点.因为我已经有节点对象和IDS已经从边缘表中加载,我想跳过这些查询,因为他们需要一个相当长的时间,更大的图形.

我尝试将这些行添加到Edge类中,但是我的JPA提供者希望我将一个映射设置为只读,而我似乎无法找到如何执行此操作的方法:

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

@Column(name = "ixNodeFrom")
private long _ixNodeFrom;
Run Code Online (Sandbox Code Playgroud)

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


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

Han*_*etz 15

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

a)更改查询

您可以通过更改查询来立即加载整个图形,从而使JPA提供程序有机会意识到它已经拥有内存中的所有内容,而不需要返回到DB:

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

(通过axtavt)

b)使用FK的只读字段

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

@Column(name = "ixNodeTo", insertable = false, updatable = false)
Run Code Online (Sandbox Code Playgroud)

(通过bravocharlie)

c)使用财产访问权限

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


此外,如帕斯卡在他的回答指出,@ManyToOne相反,我原来的职位,是不是延迟加载,但默认情况下急于加载,并且改变它需要编织为好.


小智 12

你有没有尝试过

@Column(name = "ixNodeTo", insertable = false, updatable = false)
Run Code Online (Sandbox Code Playgroud)