Hibernate - usuwanie obiektów ze zbioru relacji one-to-many

0

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()?

1

Powinno pomóc cos w stylu: https://docs.oracle.com/cd/E19798-01/821-1841/giqxy/index.html. Ogarnij cascade w Hibernate ;)
Czemu w ogole korzystasz z XML?

0

Ustawiłem cascade="all-delete-orphan" + inverse="true" - i działa :)

Tutorial z którym zacząłem korzystał z XML, więc na razie też na tym jadę, chociaż ostatecznie przeniosę to na adnotacje (w ten sposób trochę więcej się nauczę).

Potat0x napisał(a):

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ąć...

Blablabla, zacny Hibernate robi to inteligentnie i usuwa po id.

1

Jak robisz document.getItems().clear();, to usuwasz tylko powiązanie pomiędzy doc a docItem. Czyli właśnie taki null. Musisz jakoś zlecić jeszcze usunięcie docItemsów. Przez cascade albo zwyczajnie je usuwając przez delete.

1 użytkowników online, w tym zalogowanych: 0, gości: 1