2014-04-22 12 views
6

Chciałbym wiedzieć, które podejście zastosować, aby zapobiec Hibernate 4.3.4 (ze Spring i Hibernate Vaidator) przed opróżnianiem brudnych obiektów. W moim kodzie używam ręcznej implementacji metody Hibernate Validator (metoda .validate() w samej instancji), która jest wywoływana tuż przed zapisaniem encji. Metoda validate() zwraca listę błędów, jeśli są one znalezione, w przeciwnym razie wywoływana jest funkcja Session.update() w celu przechowywania obiektu, a następnie zatwierdzenia transakcji.Zapobieganie sesji hibernacji przed opróżnianiem/zapisywaniem nieprawidłowych, zabrudzonych obiektów

To działa, ale gdy sama instancja jest manipulowana (parametry zaksięgowane/żądania są ustawione w encji) encja i odpowiednia sesja hibernacji są oznaczone jako "dirty", a jednostka jest przechowywana z następną sesją .flush().

W moim przypadku chciałbym mieć wyraźną kontrolę nad podmiotami, które mogą być przechowywane i zapobiec przechowywaniu jakichkolwiek brudnych jednostek, w jaki sposób mógłbym to osiągnąć?

EDIT:

wiem mogę ręcznie regulować to przez eksmisji podmiot (lub wyczyszczenie i ponowne podmiot poprzez scalenia), ale to nie jest moim celem. Zamiast ręcznie regulować trwałość, chciałbym mieć sytuację kompensacji, że żadna jednostka, która nie została jawnie zapisana i której transakcja nie została wyraźnie zatwierdzona, nie zostanie zapisana do bazy danych (np. Przez przechwytujący?).

Odpowiedz

6

Jeśli modyfikujesz elementy i wyraźnie chcesz, aby nie były przepłukiwane, możesz je odłączyć przed modyfikacją. Oddzielone jednostki nie będą już zarządzane przez kontekst utrwalania.

Hibernate API:

session.evict(myEntity)

JPA:

entityManager.detach(myEntity)

EDIT: W przypadku, gdy chcesz odłączyć wszystkie podmioty i zarządzać tylko niektóre z nich, można wyczyścić kontekst utrwalania w pierwszej kolejności, a następnie scalanie obiektów, które należy do należy zarządzać:

Hibernate API:

session.clear(); 
managedEntity = session.merge(detachedEntity); 

JPA:

entityManager.clear(); 
managedEntity = entityManager.merge(detachedEntity); 

EDIT 2 Wszelkie zmiany podmiotów zarządzanych są wypłukiwane na transakcji popełnić. Nie jestem świadomy żadnej funkcji JPA lub Hibernate, które mogą wyłączyć to zachowanie. Więc oprócz odłączania niektórych lub wszystkich podmiotów, masz jakieś inne możliwości, ale żadna nie jest dokładnie to, czego szukasz:

  • pobierania podmioty poza transakcją, więc są one oddzielane od razu. Wydaje się to być najbliższe temu, czego chcesz - nie ma kłopotów z zarządzanymi zmianami, tylko jawne scalanie zachowałoby encję, a musiałbyś zająć mniej za pomocą interfejsu API utrwalania. Jednak nadal trzeba otworzyć sesję, aby scalić elementy, które chcesz zapisać ze zmianami.

  • mapowanie wyników zapytania na DTO/POJO (które są zawsze odłączane) za pomocą operatora NEW w zapytaniach. Takie podejście ma tę zaletę, że oddziela mapowanie trwałości od aplikacji. Jednak wprowadzenie kilku nowych klas może nie być tego warte, a nie robienie tego konsekwentnie w całej aplikacji dodaje konceptualnej złożoności.

  • praca wewnątrz transakcji, ale cofanie zamiast zatwierdzania. Nie można zapisać niczego i jest to rodzaj prostego sposobu zapobiegania synchronizacji zmian z bazą danych. Niestety, musisz ostatecznie zatwierdzić lub wycofać transakcję.

  • tworzenie głębokich kopii podmiotów do ich zmiany. Szczerze mówiąc, nie ma to dla mnie większego sensu, po prostu dodając je dla zachowania kompletności.

EDIT 3 Choć nie jest określona przez spec JPA, Hibernate i EclipseLink zarówno umożliwiają znakowanie transakcji lub nawet spowodować zestawy z jednym zapytaniu jako tylko do odczytu. Może to być użyteczne dla was, jak

Gdy trwały obiekt jest tylko do odczytu, Hibernate nie brudny sprawdzić prostych właściwości

Zmień płukania staje się trochę bardziej skomplikowana, jeśli chodzi o relacje. Proszę zapoznać się z this documentation for Hibernate lub this one for Eclipselink.

+0

Cześć Kostja, to rozwiązanie "odwrotne", ale nie to, do czego dążę. To, czego chcę, to sytuacja odwrotna, tylko obiekty jawnie zapisane i zatwierdzone mogą być przepłukiwane - domyślnie, bez odłączania, jeśli to możliwe. – Marius

+0

Oczywiście, można modyfikować kontekst utrwalania w obie strony. Zobacz edycję. – kostja

+0

Prawie tam, ale wciąż nie do końca to, co próbuję osiągnąć. Naprawdę nie chcę martwić się o brudne byty i regulować uporczywość w sposobie, w jaki opisujesz, ale raczej, na przykład za pomocą przechwytywacza, nigdy (automatycznie) opróżniaj te jednostki, gdy nie są jawnie zapisane, a transakcja nie została domyślnie zatwierdzona domyślnie, bez ponownego wprowadzania ich do sesji hibernacji, ani konieczności eksmisji ich przed opróżnieniem. – Marius

Powiązane problemy