2009-09-14 9 views
12

Blokowanie optymistyczne pomocą atrybutu wersji dla podmiotu działa dobrze i jest łatwa do wdrożenia:Jak korzystać z właściwości optymalizacji blokowania wersji Hibernacja na interfejsie użytkownika?

<version property="VERSION" type="int" column="EX_VERSION" /> 

Jednostka ma właściwość typu:

private int VERSION; 
public int getVERSION() { return VERSION; } 
public void setVERSION(int VERSION) { this.VERSION = VERSION; } 

Tak daleko, tak dobrze. Teraz metody usług zwracają obiekt przesyłania danych (DTO) dla powyższej jednostki, którą widoki wyświetlają w HTML. W przypadku stron aktualizacji atrybut VERSION jest przechowywany w ukrytym polu HTML i wysyłany wraz z formularzem.

Zamiarem jest użycie właściwości version, aby upewnić się, że aktualizacja użytkownika zakończy się niepowodzeniem, jeśli wyświetlana informacja będzie zawierała starą wersję.

Kontroler odpowiada na żądanie aktualizacji użytkowników, wywołując metodę usługi z DTO zawierającym zaktualizowane informacje (w tym właściwość version), a metoda serwisowa z kolei używa obiektu dostępu do danych (DAO), aby utrzymać zmiany:

public void update(SimpleDTO dto) { 
    SimplyEntity entity = getSimpleDao().load(dto.getId()); 
    copyProperties(dto, entity); // all properties, including VERSION copied to entity 
    getSimpleDao().update(entity); 
} 

problem polega na tym, że nieruchomość wersja kopiowane do podmiotu przez copyProperties (...) nie jest respektowany przez Hibernate. Wyszukałem przyczynę na następującym forum: https://forum.hibernate.org/viewtopic.php?f=1&t=955893&p=2418068

W skrócie, po wywołaniu load() Hibernate buforuje właściwość wersji w pamięci podręcznej sesji i nie ma znaczenia, do jakiej wartości zostanie później zmieniona. Zgadzam się, że to jest prawidłowe zachowanie, ale Bossowie polecili mi przekazanie wersji za pośrednictwem właściwości formularza HTML (jeśli jest na to lepszy wzór, chciałbym to usłyszeć).

Jednym z rozwiązań, które teraz analizuję jest eksmisja encji z sesji po tym, jak jej wersja została ustawiona za pomocą hibernateTemplate.evict (simpleEntity) przed aktualizacją. Mam nadzieję, że to działa, ale nie wydaje się skuteczne.

Chciałbym zapytać Hibernate, aby sprawdzić właściwość wersji na samej instancji, a nie tylko z pamięci podręcznej sesji.

Z góry dziękuję za odpowiedzi!

- LES

+3

Eksmitować() podmiot z sesji działa. :) pozostawiając otwarte, aby zobaczyć, czy są moje wnikliwe odpowiedzi ... – les2

Odpowiedz

10

Czy naprawdę trzeba użyć dto? Nie miałbyś tego problemu, gdybyś przekazywał rzeczywisty obiekt - ani nie musiałbyś ładować encji ponownie, co nie jest idealne dla wydajności.

Ale nawet jeśli masz uzasadniony powód do korzystania z DTO, nie do końca rozumiem, dlaczego przed zapisaniem próbowałbyś zaktualizować numer wersji na nowym jednostce , świeżo przeładowanej, o numerze. Rozważyć różne scenariusze możliwe w przepływie pracy:

  1. Podmiot jest załadowany wstępnie, zawiera wersję = V1
  2. To przeniesiony do DTO który jedzie do UI, wraca i jest gotowy do zapisania.
  3. Podmiot jest ładowany ponownie, ma wersję = V2

Masz dwie możliwości now:

  1. V1 == V2. Peachy, nie musisz nic robić.
  2. V1 jest mniejsze niż V2, co oznacza, że ​​obiekt został zaktualizowany przez kogoś innego podczas edycji. Nie ma powodu, aby próbować ustawić wersję na V1 i spróbować zapisać, ponieważ zapisywanie się nie powiedzie. Możesz go zapisać za pomocą V2 (w ten sposób unieważniając czyjeś zmiany) lub teraz zawieść (bez angażowania Hibernate).
+1

1. Ponowne załadowanie może być konieczne, ponieważ DTO może nie w pełni zawierać wszystkie pola encji, tylko podzbiór. 2. Jako komentarz (i może również przeczytać pod linkiem na dole https://forum.hibernate.org/viewtopic.php?t=977889a), Evict może pomóc tutaj. – ron

Powiązane problemy