【问题标题】:How to properly reference a class from a Collection and a direct Reference如何正确引用集合中的类和直接引用
【发布时间】:2018-10-16 11:27:07
【问题描述】:

我有两个实体:Box 和 Link。 (两者都继承自 _BaseClass,但我认为这无关紧要 - 虽然可能......)

所以一个 Box 包含链接 1、链接 2 和链接集合。

_BaseEntity:

@MappedSuperclass
public class _BaseEntity implements Comparable<_BaseEntity> {
    @Expose //
    @Id //
    @GeneratedValue() //
    protected long id;

    public _BaseEntity() {}

    public long getID() {
        if (id == 0) return creationId;
        return id;
    }

    @Override public final int hashCode() {
        return (int) getID();
    }
    @Override public final boolean equals(final Object pObj) {
        if (pObj == null) return false;
        if (getClass() != pObj.getClass()) return false;
        final _BaseEntity other = (_BaseEntity) pObj;
        return id == other.id;
    }
    @Override public int compareTo(final _BaseEntity arg0) {
        return (int) (getID() - arg0.getID());
    }
}

盒子:

@Entity
@Table(name = "PT_Box")
public class Box extends _BaseEntity {

    @Expose private String name;

    @Expose //
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "parent") //
    private Link link1;

    @Expose //
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "parent") //
    private Link link2;

    @Expose //
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = "parent") //
    private final ArrayList<Link> links = new ArrayList<>();

}

链接:

@Entity
@Table(name = "PT_Link")
public class Link extends _BaseEntity {

    @ManyToOne(fetch = FetchType.EAGER) //
    @JoinColumn(name = "parent_id") //
    private final Box parent; // dont expose for not looping!

    @Expose private String  name;
    @Expose private String  link;

    @Expose private Date    lastUpdate;
    @Expose private Date    nextUpdate;

}

问题:

  • 链接搞砸了。 'link1' 和 'link2' 显示了 'link' 的第一个元素。
  • 反之亦然:如果我设置 'link1',则列表 'links' 会将其显示为第一个元素。

怀疑:

我确定,这是由于映射

  • 框:@OneToMany(mappedBy = "parent")
  • 链接:@ManyToOne @JoinColumn(name = "parent_id")

他们还将这些链接链接到变量“link1”和“link2”中。

问题:

所以我的问题是:如何正确管理/注释?

  • 以某种方式取消映射“link1”和“link2”?
  • 将“link1”和“link2”注释为@Transient,以便引用仅由链接端设置? (如果这有效的话......)

【问题讨论】:

    标签: jpa one-to-many one-to-one many-to-one


    【解决方案1】:

    您的映射不正确。

    首先,hashCode 和 equals() 方法不应该使用生成的 ID。您可能不应该有任何 equals 或 hashCode 方法。这是最安全的方式(见http://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/Hibernate_User_Guide.html#mapping-model-pojo-equalshashcode

    其次,集合必须是 List 类型,而不是 ArrayList。

    第三:链接实体中需要三个不同的连接列(因此需要三个不同的父字段):

    • 知道哪个框包含作为其链接 1 的链接(OneToOne,OneToOne 链接 1 关联的所有者方)
    • 知道哪个框包含作为其链接 2 的链接(OneToOne,OneToOne 链接 2 关联的所有者方)
    • 知道哪个框包含作为其链接列表元素之一的链接(ManyToOne,OneToMany 链接关联的所有者方)

    【讨论】:

    • 酷,谢谢你的回答。 首先:我知道这些问题,实际上我在这里的实现被削减了,它有更多的东西,确保不会出现持久性问题。 (EclipseLink/Payara 没有它甚至会导致问题。) 第二: 为什么它必须是 List,而不是 ArrayList?我已经多次看到这一点,但到目前为止,我在使用特定类型(ArrayList、HashSeh、TreeSet 等)方面从未遇到任何问题。 第三:所以我确实需要三个独立的链接变量,每个变量都按照你写的方式注释?或者有没有我不知道的方法来注释同一个变量?
    • 2.因为 JPA 规范要求它。并且它强制它是因为 JPA 引擎必须能够使用它自己的集合实现来处理延迟加载。无论如何,对接口进行编程是一种最佳实践。 3. 是的,您需要 3 个单独的变量,按照我建议的方式进行注释。
    • 再次感谢您的详细说明。我会尝试一下,然后选择它作为解决方案。旁边有一点“但是”:Programming to interfaces is a best practice anyway. 并不完全正确。 Accept parameters as generic as possible, return values as specific as possible 就是这样。因为我总是可以毫无问题地转换类型->超类型。 supertype->type 是危险的。另外,在某些 JVM 实现中,调用接口方法比实现的方法慢。在 JPA 自定义 Collection 实现的情况下,遵循您的参数,它更像是 JPA 方面的“懒惰”。
    • 好吧,最后效果很好。必须扩展 CTOR 并创建 @Transient Box parent; 并添加 @PostLoad 方法,以将父级设置为三种可能性之一。但总而言之,它工作得很好。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    相关资源
    最近更新 更多