【问题标题】:How do I retrieve only the ID instead of the Entity of an association?如何仅检索 ID 而不是关联的实体?
【发布时间】:2016-07-12 18:13:55
【问题描述】:

我有一个看起来像这样的类:

@Entity
public class EdgeInnovation {
    @Id
    public long id;
    @ManyToOne
    public NodeInnovation destination;
    @ManyToOne
    public NodeInnovation origin;
}

还有一个看起来像这样的:

@Entity
public class NodeInnovation {
    @Id
    public long id;
    @OneToOne
    public EdgeInnovation replacedEdge;
}

所以每个表都映射到另一个,所以一个实体将引用其他实体,这些实体将引用更多实体,依此类推,因此最终将有许多实体将从数据库中获取。有没有办法只获取键的值(整数/长整数)而不是它所指的实体?像这样:

@ManyToOne(referToThisTable="NodeInnovation")
@Entity
public class EdgeInnovation {
    @Id
    public long id;
    @ManyToOne(referToTable="NodeInnovation")
    public Long destination;
    @ManyToOne(referToTable="NodeInnovation")
    public Long origin;
}

@Entity
public class NodeInnovation {
    @Id
    public long id;
    @OneToOne(referToTable="EdgeInnovation")
    public Long replacedEdge;
}

这是一个例子。我想要绿色的东西,我得到所有红色的东西。这会浪费内存和从磁盘读取的时间。

【问题讨论】:

    标签: java jpa annotations eclipselink derby


    【解决方案1】:

    对不起,我不能评论,所以我把它放在这里, 我觉得应该是这样的

    @Entity
    public class EdgeInnovation {
        @Id
        public long id;
        @ManyToOne
        public NodeInnovation destination;
        @ManyToOne
        public NodeInnovation origin;
    }
    

    另一个类是:

     @Entity
        public class NodeInnovation {
            @Id
            public long id;
            @OneToMany(mappedBy="origin")
            public List<EdgeInnovation> replacedEdges;
        }
    

    如果我弄错了情况,对不起,(你能用关系画出你的类,这样我就可以弄清楚了吗?)

    【讨论】:

    • 不,NodeInnovation 中的“replacedEdge”字段与 EdgeInnovation 中的“destination”和“origin”字段无关。将新行插入 NodeInnovation 时,“replacesEdge”将引用旧的 EdgeInnovation,而将新行插入 EdgeInnovation 时,“origin”和“destination”都将引用旧的 NodeInnovation 行。
    • 我已经编辑了这个问题,使其更加清晰。抱歉,混乱的公式和图表。我会找个借口说现在是凌晨 3 点,所以我明天会回来。
    【解决方案2】:

    为什么不在 JPA 中使用 new construction 而在 NodeInnovation 中使用自定义构造函数?基本上,在NodeInnovation 中创建一个临时属性,以便在您只需要EdgeInnovation id 时使用:

    @Entity
    public class NodeInnovation {
        @Id @GeneratedValue private Long id;
        private Integer type;
        @OneToOne
        private EdgeInnovation replacedEdge;
        @Transient
        private Long replacedEdgeId;
        public NodeInnovation() {}
        public NodeInnovation(Long id, Integer type, Long replacedEdgeId ) {
            this.id = id;
            this.type = type;
            this.replacedEdgeId = replacedEdgeId;
        }
        ...
    }
    

    像这样使用它:

    NodeInnovation n = em.createQuery("select new NodeInnovation(n.id, n.type, n.replacedEdge.id) from NodeInnovation n where n.id = 20", NodeInnovation.class).getSingleResult();
    

    您没有说明您是如何选择 NodeInnovation 的,无论是直接还是通过连接,但无论哪种方式,技巧都是 JPQL 或 CriteriaBuilder 查询中的 new NodeInnovation

    【讨论】:

    • 这看起来像我想要的,我发现如果我将“fetch = FetchType.LAZY”添加到键中,他们不会加载“下一级”,直到我访问对象女巫并不理想但做的工作。然后我继续解决其他问题,但我会在今天或明天回来告诉您它是否有效,如果有效,请将您的答案标记为正确。
    • 听起来不错。您还可以通过执行new EdgeInnovation() 然后设置id 将replacedEdgeId 存储在replacedEdge 属性中,这是在此自定义构造函数中完成的。这将具有能够在后续查询中使用此NodeInnovation 的优势。
    【解决方案3】:

    您只需将外键映射为基本映射而不是关系:

    @Entity
    public class EdgeInnovation {
        @Id
        public long id;
        @Column(name="DESTINATION_ID")
        public Long destination;
        @Column(name="ORIGIN_ID")
        public Long origin;
    }
    

    或者您可以在 EdgeInnovation 中同时访问 ID 和引用的实体,但您需要决定要使用哪个来设置映射:

    @Entity
    public class EdgeInnovation {
        @Id
        public long id;
        @Column(name="DESTINATION_ID", updatable=false, insertable=false)
        public Long destination_id;
        @ManyToOne
        public NodeInnovation destination;
        @Column(name="ORIGIN_ID", updatable=false, insertable=false)
        public Long origin_id;
        @ManyToOne
        public NodeInnovation origin;
    }
    

    在上面的示例中,origin_id 是只读的,而源引用用于设置表中的外键。不过,应该对这两个字段进行任何更改,以保持对象映射彼此同步。

    另一种选择是使用提供者的本机代码来查找引用是否是惰性的并且没有被触发,然后获取外键值。如果它已被触发,您可以只使用引用来获取 ID 值,因为它不会导致查询获取任何内容。不过,您必须查看 EclipseLink 的源代码。

    【讨论】:

    • 我无法让您的第二个选项起作用,所以我最终使用了第一个。它还解决了我在更新实体时遇到的问题。
    猜你喜欢
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    • 1970-01-01
    • 2018-02-16
    • 2011-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多