Обновление списка OneToMany после сохранения объекта в Hibernate - PullRequest
7 голосов
/ 19 июня 2010

У меня есть отношения:

// In A.java class
@OneToMany(mappedBy="a", fetch=FetchType.LAZY)
@Cascade(CascadeType.SAVE_UPDATE)
private List<B> bList;

// In B.java class
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="id_a")
@Cascade(CascadeType.SAVE_UPDATE)
private A a;

Теперь посмотрите это:

A a=new A();
// setting A

B b=new B();
// setting B
b.setA(a);

session.save(b); // this save b and a obviously

Теперь "проблема":

  • a.getId () -> текущий новый идентификатор ОК
  • a.getBList () -> по-прежнему нулевой ...

Итак, почему в этом случае bList не обновляется?

Iпопытался перезагрузить после сохранения, таким образом:

A a=new A();
// setting A

B b=new B();
// setting B
b.setA(a);

session.save(b);

A loadedA=(A)session.get(A, a.getId());

Но загруженный A все еще имеет NULL bList как a.

Естественно, чтобы избежать этой проблемы, я делаю на вашем пути:

A a=new A();
// setting A

B b=new B();
// setting B

List<B> bList=new ArrayList<B>();
bList.add(b);
a.setBList(bList);

session.save(a); // this save a and b

Таким образом, все работает хорошо, но мой вопрос: почему Id корректно обновляется после операции сохранения, а bList нет?Я должен запросить БД с оператором выбора, чтобы перезагрузить экземпляр правильно?


ОБНОВЛЕНИЕ

У меня есть это исключение

StaleStateException: Пакетное обновление вернуло неожиданное количество строк из обновления

, когда я пытаюсь сохранить сущность aOrUpdate a после удаления из нее b.

// first delete old b record
Session session=HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
a.getBList().remove(b);
b.setA(null);
session.delete(b);
// session.clear(); // this would solve my problem, but is it correct??
session.getTransaction().commit();

// then insert new b record
Session session=HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
B b=new B();
a.getBList().add(b);
b.setA(a);
session.saveOrUpdate(a);   
session.getTransaction().commit(); // this throw exception

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

session.clear является реальным решением?Я делаю (вероятно) неправильно?

обновление

удаление session.delete (b) проблема снова решена ... так, каков правильный путь?Я знаю ... я совершенно нуб с Hibernate ..

Ответы [ 2 ]

6 голосов
/ 19 июня 2010

При работе с двунаправленными ассоциациями необходимо установить связь на обеих сторонах ассоциации:

A a = new A();
B b = new B();
a.getBList().add(b);
b.setA(a);

session.persist(b);

И на самом деле, общая схема заключается в реализации таких методов управления защитными ссылками:

public class A {

    @OneToMany(mappedBy="a", fetch=FetchType.LAZY)
    @Cascade(CascadeType.SAVE_UPDATE)
    private List<B> bList = new ArrayList<B>();

    protected List<B> getListB() {
        return bList;
    }

    protected void setListB(List bList) {
        this.bList = bList;
    }

    public void addBToBs(B b) {
        bList.add(b);
        b.setA(this);
    }

    //...
}

И код становится:

A a = new A();
B b = new B();
a.addBToBs(b);

session.persist(b);

Это обсуждается в Hibernate Tutorial:

4 голосов
/ 19 июня 2010

Ох ... ок

session.refresh(a);

Это хорошо работает ... это решение, не правда?

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