2011-05-11 51 views
5

我清楚地努力理解这使帮助不胜感激...注解映射双向OneToMany/ManyToOne不提取?

我有以下映射:

@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 

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

再次感谢!

+0

查看Hibernate调试数据时是否获得任何有用的信息? – Jeremy 2011-05-11 03:08:51

+0

请参阅编辑。 BTW数据库是postgres,我也在使用tapestry-hibernate模块的tapestry环境中。 – pstanton 2011-05-11 04:20:26

回答

2

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

这里的典型方法是使用session-per-request模式,以便您在提交后立即关闭会话,并为以下事务打开另一个会话(尽管如果您使用Open Session in View pattern,它不是一个选项)。

另一种很好的做法,可以帮助解决这个问题是要同时修改的双向关系双方:

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

这样你就可以保持物体在一致的状态会话缓存。

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

+0

非常感谢!!!你救了我的命 – 2011-09-06 09:32:55

0

在你原来的问题就暗示已经数据在数据库中存在打开会话之前,这是信息要知道你将它保存在同一个会话的关键部分...

这里是关于该主题的官方Hibernate指南的方式: (取自http://community.jboss.org/wiki/HibernateFAQ-CommonProblems

我遇到了双向关联的问题。

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

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

最好在持久化类的关联管理方法中做到这一点。

我仍然有麻烦!

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

+0

这是一个列表的事实是无关紧要的。另外,如果'getChildren()'返回null,那么'Parent'已成功加载,因此从数据库读取数据似乎正在工作。 – Jeremy 2011-05-11 02:49:25

+0

修改我的答案 – 2011-05-11 03:01:05

+0

由于新信息再次修改 – 2011-05-11 23:48:57

0

在父实体中添加级联属性作为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); 

删除父时,这也将删除所有的孩子们。

+0

正确,但这里没有问题:) – 2011-05-11 23:48:37

0

The solution I use at the moment是施工过程中手动初始化集合:

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

我不知道这是一个很好的做法,但它的工作原理和简单。