Co za bałagan... AUTO_INCREMENT
to ukryta sekwencja MySQL. Radykalny problem polega na tym, że MySQL
nie można wstawić i zwrócić PK w tym samym czasie, ale Hibernate potrzebuje tego podczas INSERT
nowego podmiotu.
Problemy, które napotykasz:
- Jeśli Hibernate zapisze nowy Entity, spróbuje immerdentellly ustawić id na nowy EntityBean. Dlatego hibernacja musi przeczytać, jakiego identyfikatora użyje baza danych, zanim hibernacja zapisze nową krotkę w tabeli.
- Jeśli masz wiele serwerów, które mają dostęp do bazy danych, powinieneś pozwolić fabryce sesji hibernacji zdecydować się na użycie wbudowanej sekwencji (AUTO-INCREMENT) lub pozwolić hibernacji zdecydować (
GenerationType.AUTO
/GenerationType.IDENTITY
) jak duży jest otwarty zakres zarezerwowanych PK (praca architekta DB). (Mamy około 20 serwerów do jednej bazy danych, więc na dobrze używanym stole używamy odległości PK równej +100). Jeśli tylko jeden serwer ma dostęp do bazy danychGenerationType.TABLE
będzie poprawne.
Hibernate musi samodzielnie obliczyć następny identyfikator za pomocą max(*)+1
ale:
- Co, jeśli dwa żądania poproszą o
max(*)+1
w tym samym czasie/z takim samym skutkiem? Po prawej:ostatnia próbainsert
zawiedzie.
Musisz więc mieć tabelę LAST_IDS
w bazie danych, która przechowuje ostatnie Table-PK. Jeśli chcesz go dodać, musisz wykonać następujące czynności:
- Rozpocznij transakcję optymistyczną do odczytu.
- SELECT MAX(address_id) FROM LAST_IDS
- przechowuj maksimum w zmiennej java, np.:$OldID.
- $NowyID =$StaryID + 1. (+100 w pesymistycznej blokadzie)
- AKTUALIZUJ LAST_IDS USTAW adres_id=
$newID
GDZIE adres_id=$oldID
? - zatwierdź transakcję optymistyczną do odczytu.
- jeśli zatwierdzenie się powiodło, przechowaj
$newID
dosetID()
w HibernateBean, który chcesz zapisać. - Na koniec pozwól Hibernate wywołać wstawkę.
To jedyny sposób, jaki znam.
BTW:Hibernate-Entitys powinny używać dziedziczenia tylko wtedy, gdy baza danych obsługuje dziedziczenie między tabelami, takie jak PostgreSQL
lub Oracle
.