Избежание JPA TransientObjectException без сохранения всего вручную
У меня есть иерархия объектов, как это (отклоняя все поля, такие как идентификатор, сеттеры / получатели и т. Д.):
@Entity
class A {
@OneToOne(cascade=CascadeType.ALL)
private B b;
}
@Entity
class B {
@OneToOne(cascade=CascadeType.ALL)
private A a;
@OneToOne(cascade=CascadeType.ALL)
private C c;
}
@Entity
class C {
private int x;
}
Все лица имеют @Id @GeneratedValue private Long id;
Я использую JPA с Hibernate и MySQL и имею DAO для A
который делает простой entityManager.merge(a); entityManager.flush();
Теперь эта конструкция используется в проекте JSF, где я создаю новый A
с новым B
но значение для C
взят из базы данных, следовательно, это существующий объект. Этот недавно заполненный объект отображается на странице и сохраняется только при нажатии кнопки сохранения, поэтому создание и сохранение выполняются в двух разных транзакциях.
Когда я пытаюсь сделать dao.save(a)
Я получаю org.hibernate.TransientObjectException
не очень удивительно, так как значение для c
в классе B
уже существует в базе данных.
Теперь актуальный вопрос: могу ли я как-то избежать этой проблемы БЕЗ каскадного сохранения вручную? Я говорю о десятках B
классы, каждый с десятками C
с - это было бы полностью против моей идеи каскадирования...
Любые идеи приветствуются!
2 ответа
Я обошел проблему, выполнив следующие действия:
В A
Я создал метод List<B> getBs()
который получает все й B классов. В B
Я создал метод List<C> getCs()
, Теперь в Дао я делаю
public void save(A a) {
for (B b : a.getBs()) {
for (C c : b.getCs()) {
if (c != null) {
if (c.getId() == null) {
entityManager.persist(c);
} else {
entityManager.merge(c);
}
}
}
}
super.save(a);
}
Теперь мне нужно только следить за B
с и C
с, но это все же лучше, чем обход всего дерева объектов...
Там может быть проблема из-за аннотации. Вы можете получить помощь из этого примера, чтобы решить вашу проблему.