【问题标题】:JPA/Hibernate: bidirectional OneToMany/ManyToOne relation only works unidirectionalJPA/Hibernate:双向 OneToMany/ManyToOne 关系仅适用于单向
【发布时间】:2013-06-05 10:40:40
【问题描述】:

我目前在使用 OneToMany/ManyToOne-Mapping 时遇到问题。映射如下所示:

public class A implements Serializable {
    @EmbeddedId
    private AId id;

    // Other stuff...
}

@Embeddable
public class AId implements Serializable {
    @ManyToOne
    @JoinColumn(name = "B_ID", nullable = false)
    private B b;

    // Other stuff...
}

public class B implements Serializable {
    @OneToMany(mappedBy = "id.b")
    private List<A> as;

    // Other stuff...
}

如果我尝试使用对象 A 访问对象 B,一切正常,但反向根本不起作用。关系始终为空。

A objectA = findAById(id);
B objectB = objectA.getB(); // OK

// But... for example
objectB.getAs(); // returns null

我编写了一个小查询来使用对象 B 的主键获取所有 As:

SELECT as FROM B b, IN(b.as) as WHERE b.id = :id

这很完美,我得到了预期的结果。 我也检查了数据库中保存的内容,没关系。有人知道为什么这种关系只在一个方向上有效吗?

问候,

亚历克斯

【问题讨论】:

  • 我怀疑 mappedBy 是否支持嵌套属性名称(我记得在旧版本的 Hibernate 中不支持)
  • 同时它似乎得到了支持。 hibernate.atlassian.net/browse/ANN-381
  • JPA 不允许embeddedIds 包含关系,所以这不符合JPA。当您可以将关系放在实体本身中时,为什么还要将关系放在嵌入式对象中呢?使用 mapid 甚至 ID 类可以让您只使用实体,而不必在实体中维护一个嵌入的 id 类。
  • 还要检查您是否设置了关系的双方。快速检查将强制刷新 objectB,以便提供者转到数据库以填充 objectBb.as 关系,而不是使用可能缓存的内容。试试 em.refresh(objectB);
  • 使用 MapsId 注释在实体中建立关系会给我一个 org.hibernate.PropertyAccessException 异常。听起来有点像stackoverflow.com/questions/7984356/…,但同时也解决了这个错误:(

标签: java hibernate jakarta-ee jpa


【解决方案1】:

这是因为默认情况下@onetomany 具有延迟获取功能。你可以用这个来解决这个问题 fetch = FetchType.EAGER

public class B implements Serializable {
    @OneToMany(mappedBy = "id.b", fetch = FetchType.EAGER)
    private List<A> as;

    // Other stuff...
}

【讨论】:

  • 这意味着延迟获取永远不会加载数据。这不是真的。应在首次访问关系期间加载数据。否则,延迟获取的整个概念将毫无用处。问题是embeddedIds 不允许有关系(就像上面发布的Chris)。
猜你喜欢
  • 2013-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多