2011-07-01 3 views
1

私のコードは次のようになります。 setChildren()の名前をnullとする理由は何ですか?フィールドがヌルである間にsetterで関連オブジェクトを使用するJPA/Hibernate

public class Node { 
     private String id, name, parentName; 
     private Set<Node> children = new HashSet<Node>(); 
     private Node parent; 
     private Set<String> childrenNames = new HashSet<String>(); 

     @Id @GeneratedValue public String getId() { return id; } 

     public String getName() {return name;} 

     @ManyToOne @JoinColumn(name="PARENT_ID") public Node getParent(){retrun parent;} 

     @OneToMany(cascade=CascadeType.ALL, mappedBy="parent", fetch=FetchType.EAGER) 
     public Set<Client> getChildren(){return Collections.unmodifiableSet(children)} 

     @Transient public String getParentName() { return parentName;} 
     @Transient public Set<String> getChildrenNames() {return childrenNames;} 

     // PROBLEM here ------------ 
     public void setChildren(Set<Node> children) { 
     this.children = children; 
     for(Node child : children) { 
      childrenNames.add(child.getName()); //Adds NULL !!!!!! 
     } 
     } 

     // Other Setters 

    } 

am n00bですので、このままお待ちください。

+1

このコードをデバッグし、setChildren(...)の中にブレークポイントを設定すると、子ノードオブジェクトのすべてのフィールド(@Idを除く)がnullに設定されていますか? –

+0

が正しい。 '@ Id 'を除くすべてのフィールドは' null'です。助けてください – Ram

+0

同様の問題のコレクションについてはhttp://stackoverflow.com/questions/6217096/hibernate-mapping-returns-null-propertiesも参照してください。 – Gregor

答えて

2

これは推測ですが、子オブジェクトに実際にHibernateによるバッキングSQLクエリのデータが取り込まれる前に、Node.setChildren()が呼び出されている可能性があります。 Hibernateは@Idの値セットだけでオブジェクトを作成することがあります。遅延プロキシについてのドキュメントを読んでいるなら、その証拠を見るべきです。私はそれから、Hibernateが子のNodeオブジェクトを作成したが、親ノードを最初に取り込む必要があるため、それらのデータにまだデータを設定していないことが疑わしい。基本的にあなたのセッターはプロセスの早い段階で発砲しています。

コードをデバッグし、setChildren()およびsetName()にブレークポイントを追加することで、これを確認できます。上記のコードではsetName()メソッドを表示しませんが、省略したと仮定します。また、ブレークポイントでスタックをチェックして、setterが呼び出されたときにHibernateが何をしているのかを知ることができます。

つの回避策は次のように()GetChildrenメソッドにsetChildren()からロジックを追加することです:

@Transient public Set<String> getChildrenNames() { 
    if (children.size() != childrenNames.size() { 
     childrenNames.removeAll(); 
     for(Node child : children) { 
      childrenNames.add(child.getName()); 
     } 
    } 
    return childrenNames; 
} 

これは一度だけ実行する必要があります可能性があり、時間によってゲッタが呼び出された子供のデータをすべき人口となる。あるいは、「childrenNames」を移入するロジックをgetter/setter以外のメソッドに置き、クエリの後に手動で呼び出すこともできます。

+0

私は、Hibernateのすべてのフィールド直接アクセスに切り替え、ロジックをゲッターに移動しました。今働いている。 – Ram

+0

アノテーション '@ PostLoad'が動作しませんでした – Ram

1

子の名前がnullの場合、書かれたコードはうれしいことにchildrenNamesにnullを追加します。

+0

子の名前がnullではありません。事実、彼らは後に人口が集まる。 setter中のみnullとして返されます。 – Ram

関連する問題