Jaký nepořádek... AUTO_INCREMENT
je skrytá sekvence MySQL. Radikální problém je, že MySQL
nelze vložit a vrátit PK současně, ale Hibernate to potřebuje, zatímco INSERT
vytvoření nové entity.
Problémy, na které narazíte:
- Pokud Hibernate uloží novou entitu, pokusí se nastavit id imerdentelly na novou EntityBean. Proto hibernace musí přečíst, jaké ID bude databáze používat, než hibernace uloží novou n-tice do tabulky.
- Pokud máte více serverů, které přistupují k databázi, musíte nechat továrnu relací hibernace, aby se rozhodla použít vestavěnou sekvenci (AUTO-INCREMENT) nebo nechat rozhodnout hibernaci (
GenerationType.AUTO
/GenerationType.IDENTITY
) jak velký je otevřený rozsah rezervovaných PK (Job of a DB-Architect). (Máme asi 20 serverů na jednu databázi, takže na dobře používaném stole používáme PK-vzdálenost +100). Pokud má pouze jeden server přístup k databáziGenerationType.TABLE
bude správné.
Hibernate musí vypočítat další id sami pomocí max(*)+1
ale:
- Co když dva požadavky požádají o
max(*)+1
ve stejnou dobu/se stejným výsledkem? Vpravo:Poslední pokus oinsert
selže.
Takže potřebujete mít tabulku LAST_IDS
v databázi, kdo ukládá poslední Table-PK's. Pokud chcete jeden přidat, musíte provést tyto kroky:
- Zahajte transakci optimalizovanou pro čtení.
- VYBERTE MAX (ID_adresy) Z LAST_IDS
- uložte maximum do proměnné java, např.:$OldID.
- $NewID =$StaréID + 1. (+100 v pesimistickém zámku)
- UPDATE LAST_IDS SET address_id=
$newID
WHERE address_id=$oldID
? - potvrdit transakci optimalizovanou pro čtení.
- pokud bylo potvrzení úspěšné, uložte
$newID
nasetID()
v HibernateBean, který chcete uložit. - Nakonec nechejte Hibernate zavolat insert.
Tohle je jediný způsob, jak to vím.
BTW:Hibernate-Entitys použijí dědičnost pouze v případě, že databáze podporuje dědičnost mezi tabulkami jako PostgreSQL
nebo Oracle
.