JPA / Hibernate, использующий связанный объект в установщиках, в то время как поля являются нулевыми - PullRequest
1 голос
/ 01 июля 2011

Мой код выглядит следующим образом. Почему я получаю имя в setChildren() как null ??

    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

    }

Я n00b, поэтому, пожалуйста, помогите с этим.

Ответы [ 2 ]

2 голосов
/ 04 июля 2011

Это предположение, но я подозреваю, что Node.setChildren () вызывается до того, как дочерние объекты фактически заполнятся данными из вспомогательного SQL-запроса Hibernate. Hibernate иногда создает объекты только с установленным значением @Id; если вы читаете документацию о ленивых прокси, вы должны увидеть доказательства этого. Я подозреваю, что Hibernate создал дочерние объекты Node, но еще не заполнил их данными, потому что он должен сначала заполнить родительский Node. В основном ваш сеттер слишком рано стреляет.

Вы можете проверить это, отладив код и добавив точку останова в setChildren () и setName (). Вы не показываете метод setName () в приведенном выше коде, но я предполагаю, что вы просто его опустили. Также проверьте стек в точке останова, чтобы понять, что делает Hibernate во время вызова вашего установщика.

Один обходной путь - добавить логику из setChildren () в getChildren () следующим образом:

@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, и вызывать его вручную после запроса.

1 голос
/ 01 июля 2011

Если имя ребенка равно нулю, то написанный код успешно добавит ноль в набор childrenNames.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...