Vilken röra... AUTO_INCREMENT
är MySQL:s dolda sekvens. Det radikala problemet är att MySQL
kan inte infoga och returnera PK samtidigt, men Hibernate behöver detta medan INSERT
en ny enhet.
Problemen du stöter på:
- Om Hibernate sparar en ny Entity, försöker han ställa in ID:t till den nya EntityBean. Därför måste hibernate läsa vilket ID som databasen använder innan viloläge sparar den nya Tuple i tabellen.
- Om du har flera servrar som har åtkomst till databasen ska du låta hibernates sessionsfabrik välja att använda den inbyggda sekvensen (AUTO-INCREMENT) eller låta viloläge bestämma (
GenerationType.AUTO
/GenerationType.IDENTITY
) hur stort det öppna utbudet av reserverade PK är (Job of a DB-Architect). (Vi har cirka 20 servrar till en databas, så på en välanvänd tabell använder vi ett PK-avstånd på +100). Om bara en server har tillgång till databasenGenerationType.TABLE
ska vara korrekt.
Hibernate måste själv beräkna nästa ID med max(*)+1
men:
- Vad händer om två förfrågningar ber om
max(*)+1
samtidigt/med samma resultat? Höger:Det senaste försöket attinsert
kommer misslyckas.
Så du måste ha en tabell LAST_IDS
i databasen vem som lagrar de sista tabell-PK:erna. Om du vill lägga till en, måste du göra följande steg:
- Starta läsoptimistisk transaktion.
- VÄLJ MAX(adress_id) FRÅN LAST_IDS
- lagra maximalt i en java-variabel, dvs:$OldID.
- $NewID =$OldID + 1. (+100 i pessimistiskt lås)
- UPPDATERA LAST_IDS SET address_id=
$newID
WHERE address_id=$oldID
? - begå den läsoptimistiska transaktionen.
- om commit lyckades, lagra
$newID
tillsetID()
i HibernateBean du vill spara. - Låt slutligen Hibernate anropa infogningen.
Detta är det enda sättet jag vet.
BTW:Hibernate-Entitys ska bara använda arv om databasen stöder arv mellan tabeller som PostgreSQL
eller Oracle
.