2011-05-11 54 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>; 

我不知道這是一個很好的做法,但它的工作原理和簡單。