2010-04-29 1 views
2

EDIT: Решено, но я не знаю, что теперь изменилось. Если кто-нибудь сможет объяснить, что произошло по-другому, я был бы признателен.JPA Изменения косвенного набора не отражены в Spring frontend

Путь теперь работает это путем объединения только родителя, а не ребенка вообще, как так:

Parent parent = child.getParent(); 
parent.getChildren().add(child); 
getJpaTemplate().merge(parent); 

Теперь, кажется, работает, но я не совсем понимаю, почему это будет пока моя предыдущая попытка не сделала этого.

Оригинальная попытка/вопрос:

У меня возникли проблемы с Spring JPA и IndirectSets. У меня есть два объекта: «Родитель и ребенок», определенные ниже. У меня есть форма Spring, в которой я пытаюсь создать нового Child и связать его с существующим Parent, а затем все отразится в базе данных и в веб-интерфейсе. Что происходит, так это то, что он попадает в базу данных, но пользовательский интерфейс, похоже, не согласен.

две сущности, которые связаны друг с другом в отношениях OneToMany как так:

@Entity 
@Table(name = "parent", catalog = "myschema", uniqueConstraints = @UniqueConstraint(columnNames = "ChildLinkID")) 
public class Parent { 
    private Integer id; 
    private String childLinkID; 

    private Set<Child> children = new HashSet<Child>(0); 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id", unique = true, nullable = false) 
    public Integer getId() { 
     return this.id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    @Column(name = "ChildLinkID", unique = true, nullable = false, length = 6) 
    public String getChildLinkID() { 
     return this.childLinkID; 
    } 

    public void setChildLinkID(String childLinkID) { 
     this.childLinkID = childLinkID; 
    } 

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent") 
    public Set<Child> getChildren() { 
     return this.children; 
    } 

    public void setChildren(Set<Child> children) { 
     this.children = children; 
    } 
} 

@Entity 
@Table(name = "child", catalog = "myschema") 
public class Child extends 
    private Integer id; 
    private Parent parent; 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id", unique = true, nullable = false) 
    public Integer getId() { 
     return this.id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    @ManyToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "ChildLinkID", referencedColumnName = "ChildLinkID", nullable = false) 
    public Parent getParent() { 
     return this.parent; 
    } 

    public void setParent(Parent parent) { 
     this.parent = parent; 
    } 
} 

И, конечно же, различные простые свойства на каждом из них. Теперь проблема в том, что когда я редактирую эти простые свойства из моего интерфейса Spring, все работает красиво. Я могу сохранить новые объекты этих типов, и они появятся при использовании JPATemplate для поиска, скажем, для всех родителей (getJpaTemplate(). Find («выберите p из Parent p»)) или для отдельных объектов по ID или другое свойство.

Проблема, с которой я столкнулся, заключается в том, что сейчас я пытаюсь создать нового ребенка, связанного с существующим родителем, по ссылке со страницы Родительского. Вот важные биты контроллера (обратите внимание, что я поместил Foo JPA в контроллере здесь, чтобы сделать его более четким, фактическое JpaDaoSupport на самом деле в другом классе, соответственно многоуровневый):

protected Object formBackingObject(HttpServletRequest request) throws Exception { 
    String parentArg = request.getParameter("parent"); 
    int parentId = Integer.parseInt(parentArg); 
    Parent parent = getJpaTemplate().find(Parent.class, parentId); 
    Child child = new Child(); 
    child.setParent(parent); 
    NewChildCommand command = new NewChildCommand(); 
    command.setChild(child); 
    return command; 
} 

protected ModelAndView onSubmit(Object cmd) throws Exception { 
    NewChildCommand command = (NewChildCommand)cmd; 
    Child child = command.getChild(); 
    child.getParent().getChildren().add(child); 
    getJpaTemplate().merge(child); 
    return new ModelAndView(new RedirectView(getSuccessView())); 
} 

Как я уже сказал, Я могу запустить форму и заполнить новые значения для Ребенка - детали родителя даже не отображаются. Когда он возвращается к контроллеру, он проходит и сохраняет его в базовую базу данных, но интерфейс никогда не отражает его. Как только я перезапущу приложение, он все там и заселен соответствующим образом.

Что я могу сделать, чтобы очистить это? Я попытался вызвать дополнительные слияния, попытался обновить (что дало исключение транзакции), все, что просто не написало мой собственный код доступа к базе данных. Я убедился, что каждый класс имеет соответствующие equals() и hashCode(), имеет полную отладку JPA, чтобы видеть, что он делает соответствующие SQL-вызовы (он, похоже, не вызывает никаких новых вызовов в таблице Child) и наступил через отладчик (все это в IndirectSets, как и ожидалось, а также между сохранением и отображением Parent объект получает новый адрес памяти). Каков мой следующий шаг?

ответ

0

Я не уверен это что-то делать с вашей проблемой, но почему у вас есть childLinkID недвижимости в вашем Parent классе? Это кажется действительно странным, тем более, что вы используете соответствующий столбец для соединения. Интересно, как можно работать с этим отображением, и я исправлю это. Можете ли вы попробовать (также удалите referencedColumnName, вам это не нужно)?

И, кстати, почему бы вам не установить обе стороны связи между Parent и Child в том же методе? Это делает код трудным для чтения и поддерживает ИМО.


Вы редактировали вопрос, а я отвечал и изменил каскадирование от Parent к Child, но это похоже на работу вокруг реальной проблемы, и я не уверен, что вы не будете сталкиваться с другими проблемами. Попытайтесь исправить свое сопоставление, как я предложил.

+0

Причина в том, что в реальной модели, которая вызывала проблему, которую я упростил к этому, у меня есть данные реального мира, которые должны использоваться сами по себе как свойство родительского класса, которое является прямым отображением для ребенка здесь. На самом деле, есть два других дочерних класса, которые я должен реализовать, каждый из которых ссылается на свойство/different/property родителя. (Я не проектировал модель данных, чтобы отвлечь ваш следующий вопрос/предложение.) Чтобы ответить на второй вопрос, это связано с тем, что я добавил ссылку от родителя к ребенку как исправление этой проблемы (и при ее исправлении) , Это изменилось в реальном коде. – Jon

+0

Я также изменил сущности так, что я переместил аннотации JPA от методов getXXX к самим объявлениям переменных, о которых я забыл упомянуть. Могло ли это устранить проблему? – Jon

+0

@Jon 1) Я не уверен, что понял необходимость в свойстве 'childLinkID', и мне интересно, как JPA обрабатывает все это 2) *« это потому, что я добавил ссылку от родителя к ребенку как исправление этой проблемы » * - это ** требуется ** с двунаправленными ассоциациями, вы должны установить обе стороны ссылки. 3) * «Я также изменил сущности, так что я переместил аннотации JPA от методов getXXX к самим объявлениям переменных» * - это ничего не меняет. На самом деле, я все еще думаю, что есть что-то эзотерическое, и что изменение каскадного эффекта сработало. –