【问题标题】:Session.contains return false for object that load by OneToMany relation对于通过 OneToMany 关系加载的对象,Session.contains 返回 false
【发布时间】:2018-01-05 02:46:57
【问题描述】:

考虑存在两个对象AB,其中A包含与B的OneToMany关系。我加载对象 A 并在其 Bs 上进行迭代。但问题是当我调用Session.contains(B[0]) 时,它会返回false

在上一个会话中,我加载了对象b (b=B[0]),在这个会话中,在加载对象A之前我调用了b2=Session.merge(b),当我再次加载对象A时,它用b填充B字段而不是b2;

有没有人知道为什么用b 而不是b2 填充B

【问题讨论】:

    标签: java hibernate session orm hibernate-mapping


    【解决方案1】:

    您可能有一个 Set 作为您的一对多集合,并且您的 equals/hashCode 正在使用数据库标识符。

    当您将元素添加到集合时,hashCode 用于将元素放入正确的存储桶中。刷新会话后,会分配标识符,因此 hashCode 会更改。但该对象仍被放置在旧的 hashCode 存储桶中。当您尝试使用新的 hashCode 值加载它时,您将不会再看到您的反对。

    这就是为什么在域模型实体中实现 equals/hashCode 或 use this trick if you don't have any business key 时需要 use a business key

    【讨论】:

    • 没有。我有一个 ArrayList 作为我的 OneToMany 集合
    • 你是用实体实现equals和hashcode吗?
    • 是的。我使用这些:public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Message message = (Message) o; if (id != message.id) return false; return true; }public int hashCode() { return (int) (id ^ (id >>> 32)); }
    • 如果您使用合成的自动递增标识符(IDENTITY、SEQUENCE、TABLE 序列),那么您需要改用业务密钥。插入实体前后 hashCode/equals 将不一致。
    • 谢谢。我很高兴能帮上忙。
    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 2021-05-17
    • 2011-12-17
    • 1970-01-01
    • 1970-01-01
    • 2023-02-09
    • 2012-07-25
    • 2021-11-19
    相关资源
    最近更新 更多