Я пытаюсь удалить дочерний элемент из двунаправленной ассоциации. Я понимаю, что если я запрашиваю экземпляр Employee, а затем использую метод getChildren()
для извлечения связанного дочернего элемента, управляются как родительская, так и дочерняя записи. Теперь, когда я звоню child.setParent(null)
и parent.getChildren().remove(child)
, оба обновления должны сохраняться при совершении транзакции, но я получаю: org.hibernate.AssertionFailure: collection [org.rand.model.Employee.children] was not processed by flush()
исключение, если я не вызову слияние по дочернему элементу или не выберет дочерние элементы по запросу.коллекция не обрабатывалась flush()
Может кто-нибудь объяснить, почему это происходит?
Я использую спящий режим 3.5.6-Final
Благодарности
UPDATE: Через некоторое время отладки я нашел код, который вызывает эту ошибку, и я должен быть случайно удалил при отправке вопроса. Я искренне извиняюсь за это.
Виновник был обычным OneToManyInverseCheck
bean validator, который проверял, установлены ли отношения как для родителя, так и для ребенка. Это вызвало загрузку дополнительных объектов (детей детей) во время операции фиксации.
Entity:
@Entity
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.TABLE)
private int id;
@Version
private int version;
private String name;
@ManyToOne
private Employee parent;
@OneToMany(mappedBy="parent")
@OneToManyInverseCheck(inverseFieldName="parent")
private List<Employee> children;
//get/set methods ommitted
}
Простой JUnit:
public class JPAUpdate {
private static EntityManagerFactory emf;
private EntityManager em;
@BeforeClass
public static void init() {
emf = Persistence.createEntityManagerFactory("myapp-db");
}
@Before
public void setUp() throws Exception {
em = emf.createEntityManager();
}
@Test
public void removeChildWithMerge() {
em.getTransaction().begin();
Employee e = em.createQuery("from Employee e where e.children is not empty order by e.id asc", Employee.class).getResultList().get(0);
Employee child = e.getChildren().get(0);
child.setParent(null);
e.getChildren().remove(child);
// removing this merge causes org.hibernate.AssertionFailure: collection [org.rand.model.Employee.children] was not processed by flush()
em.merge(child);
em.getTransaction().commit();
}
@Test
public void removeChildWithFetch() {
em.getTransaction().begin();
Employee e = em.createQuery("from Employee e left join fetch e.children where e.children is not empty order by e.id asc", Employee.class).getResultList().get(0);
Employee child = e.getChildren().get(0);
child.setParent(null);
e.getChildren().remove(child);
//em.merge(child); - no merge needed
em.getTransaction().commit();
}
@Test
public void removeChild() {
em.getTransaction().begin();
Employee e = em.createQuery("from Employee e left join fetch e.children where e.children is not empty order by e.id asc", Employee.class).getResultList().get(0);
Employee child = e.getChildren().get(0);
child.setParent(null);
e.getChildren().remove(child);
//em.merge(child); - no merge needed
em.getTransaction().commit();
}
}
его нужно управлять, поэтому отметьте «em.contains()». Если он управляется, вам никогда не придется вызывать слияние по спецификации JPA. Если он не управляется, тогда вы должны задать вопрос, почему Hibernate передает не управляемые объекты ... –