注释映射双向OneToMany / ManyToOne没有提取?

时间:2011-05-11 02:37:58

标签: java hibernate

我显然很难理解这一点,所以非常感谢...

我有以下映射:

@Entity
@Table(name = "parent")
public class ParentEntity
{
...
    @Id
    @Column(name = "parent_id")
    private Long id;
...
    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
    private List<ChildEntity> children;
...
}

@Entity
@Table(name = "child")
public class ChildEntity
{
...
    @Id
    @Column(name = "child_id")
    private Long id;
...
    @ManyToOne(fetch = FetchType.EAGER)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "parent_id")
    private ParentEntity parent;
...
}

在我的数据库中我有:

parent
------
parent_id: 1

child
------
child_id: 1, parent_id: 1

然而

((Parent) session.get(Parent.class, 1)).getChildren()

返回null。

谁能看到我遗失的东西?

谢谢,p。

修改

对于会话状态似乎更为如此,因为集合未在同一会话的上下文中填充,但集合将在下一个会话中填充...

考虑以下事项:

void setupRender()
{
    debug("existing not just added", (ParentEntity) session.get(ParentEntity.class, 13L));

    ParentEntity parent = new ParentEntity();
    session.save(parent);

    ChildEntity child = new ChildEntity();
    child.setParent(parent);
    session.save(child);

    debug("new one before commit", parent);

    sessionManager.commit();

    debug("new one after commit", parent);

    debug("new one after re-fetch", (ParentEntity) session.load(ParentEntity.class, parent.getId()));
}

private void debug(String prefix, ParentEntity parent)
{
    log.debug(prefix + ": parent id: " + parent.getId() + ", Children is "
            + (parent.getChildren() == null ? "null" : "size:" + parent.getChildren().size()));
}

产生以下输出:

DEBUG - existing not just added: parent id: 13, Children is size:1
DEBUG - new one before commit: parent id: 23, Children is null
DEBUG - new one after commit: parent id: 23, Children is null
DEBUG - new one after re-fetch: parent id: 23, Children is null

所以,如果它是由于会话状态,并且提交不足以触发重新获取,那么我需要做些什么来获取映射以获取集合?

再次感谢!

4 个答案:

答案 0 :(得分:2)

是的,提交不会触发刷新会话缓存。

此处的典型方法是使用会话每请求模式,以便在提交后立即关闭会话,并为以下事务打开另一个会话(尽管如果您使用Open Session in View pattern则不是一个选项)

可能有助于解决此问题的另一个好习惯是同时修改双向关系的双方:

public class ParentEntity {
    ...
    public void addChild(ChildEntity c) {
        children.add(c);
        c.setParent(this);
    }
}

这样,您可以使会话缓存中的对象保持一致状态。

最后,如果您确实需要刷新会话中的对象,可以在其上调用Session.refresh()

答案 1 :(得分:1)

在父实体中添加cascade属性作为OneToMany的一部分可能会解决问题。

@Entity
@Table(name = "parent")
public class ParentEntity
{
...
    @Id
    @Column(name = "parent_id")
    private Long id;
...
    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER, cascade=CascadeType.ALL)
    private List<ChildEntity> children;
...
}

然后继续行

ParentEntity parent = new ParentEntity();

ChildEntity child = new ChildEntity();
child.setParent(parent);
parent.getChildren().add(child);
session.save(parent);

删除父母时,这也会删除所有孩子。

答案 2 :(得分:0)

在您的原始问题中,它暗示数据在您打开会话之前已经存在于数据库中,这是知道您将其保存在同一会话中的关键信息......

顺便说一下,这是关于该主题的官方Hibernate指南: (取自http://community.jboss.org/wiki/HibernateFAQ-CommonProblems

我遇到双向关联问题。

更新双向关联时,必须更新两端。

parent.getChildren().add(child);
child.setParent(parent);

最好在持久化类的关联管理方法中执行此操作。

我还有问题!

阅读文档!在参考文档的第16章中有一个关于“父/子关系”的详细部分,包括代码示例。

答案 3 :(得分:0)

The solution I use at the moment是在构建期间手动初始化集合:

private List<ChildEntity> children 
    = new ArrayList<ChildEntity>;

我不确定这是不是一个好习惯,但它有效并且很简单。