Mam tabele: documents
, documents_items
- tak, jak w załączniku i odpowiednio klasy Document
, DocumentItem
. //documents_items == pozycje na dokumentach
Na dokumencie może być wiele przedmiotów - i mapuję je sobie jako zbiór.
Mapowanie w Document:
<set name="items" cascade="all">
<key column="document_id"/>
<one-to-many class="DocumentItem"/>
</set>
Użytkownik może dodawać i usuwać pozycje z dokumentów. Dodawanie działa. Z usuwaniem jest dziwny problem.
Dostaję takie wyjątki
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
...
Caused by: java.sql.SQLException: ORA-01407: cannot update ("MAGAZYNIER"."DOCUMENTS_ITEMS"."DOCUMENT_ID") to NULL
Same wyjątki mnie nie dziwią: DOCUMENT_ID
nie może być nullem.
Co mnie zastanawia to ich przyczyna: Hibernate próbuje zrobić coś takiego:
Hibernate: update documents_items set document_id=null where document_id=? and document_item_id=?
Tego nie rozumiem. Dlaczego ustawia document_id
na null
, gdy ja w aplikacji usuwam element ze zbioru?
public class Document implements Indexed {
private Set<DocumentItem> items;
}
ArrayList ar = new ArrayList<>(Arrays.asList(documentItemsTable.getItems().toArray()));
Set<DocumentItem> newItemsSet = new HashSet<DocumentItem>(ar);
document.getItems().clear();
document.getItems().addAll(newItemsSet);
try {
DAO.update(document);
System.out.println("save");
} catch (RowNotFoundException e) {
e.printStackTrace();
}
public static void update(Indexed object) throws RowNotFoundException {
try (Session session = HibernateSessionFactory.openSession()) {
if (checkIfExists(session, object)) {
Transaction tr = session.beginTransaction();
session.update(object);
tr.commit();
} else {
throw new RowNotFoundException(object.getClass() + " object:" + object + " does not exist in database.");
}
}
}
Teraz tak się zastanawiam, jak Hibernate miałby to usuwać. Ze zbioru zniknęła pozycja, więc też jej id. Więc nie można usunąć zwyczajnie po id. Można by obliczyć różnicę dwóch zbiorów: z aplikacji i z bazy, a następnie usunąć z bazy rekordy z tak otrzymanego zbioru. Tak to jest zaimplementowane?
Czy to w ogóle ma prawo działać? Czy może powinienem usuwać elementy ręcznie np. za pomocą zwykłego session.delete()
?