JPA / Hibernate:双向OneToMany / ManyToOne关系仅在单向情况下起作用

3

我目前遇到了OneToMany/ManyToOne映射的问题。映射如下:

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,一切都正常工作,但反过来则完全不行。关系总是null。
A objectA = findAById(id);
B objectB = objectA.getB(); // OK

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

我写了一个小查询,使用对象B的主键,获取所有A。
SELECT as FROM B b, IN(b.as) as WHERE b.id = :id

这个很好运作,我得到了期望结果。 我也检查了在数据库中持久化的内容,一切都没问题。有人知道为什么这个关联只能单向工作吗?
谢谢, Alex

我怀疑mappedBy是否支持嵌套属性名(我记得在旧版本的Hibernate中它是不支持的)。 - Adrian Shum
同时,这似乎得到了支持。https://hibernate.atlassian.net/browse/ANN-381 - Alex
JPA不允许嵌入式ID包含关系,因此这不符合JPA的规范。为什么要将关系放在嵌入式对象中呢?当您可以将关系放在实体本身中时,使用mapsid甚至是ID类可以让您仅使用实体并避免在实体内维护嵌入式ID类。 - Chris
1
还要检查是否设置了关系的两个方向。一个快速的检查方法是强制刷新objectB,这样提供者就会去数据库中填充objectBb.as关系,而不是使用可能被缓存的内容。可以尝试使用em.refresh(objectB)来实现。 - Chris
使用MapsId注释在实体中建立关系会导致org.hibernate.PropertyAccessException异常。听起来有点像https://dev59.com/d1zUa4cB1Zd3GeqP69Wo,但是这个bug在此期间已经被解决了:( - Alex
遵循此帖子可以解决PropertyAccessException的问题http://forum.springsource.org/showthread.php?101410-Hibernate-JPA-with-MapsId,但主要问题仍然存在。关系仍然是单向的。 - Alex
1个回答

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在上面发布的那样)。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接