Sikke et rod... AUTO_INCREMENT
er MySQL's skjulte sekvens. Det radikale problem er, at MySQL
kan ikke indsætte og returnere PK'en på samme tid, men Hibernate har brug for dette, mens INSERT
ing af en ny enhed.
De problemer, du støder på:
- Hvis Hibernate gemmer en ny Entity, forsøger han at indstille id'et til den nye EntityBean. Derfor skal hibernate læse, hvilket ID vil databasen bruge, før dvaletilstand gemme den nye Tuple til bordet.
- Hvis du har flere servere, der tilgår databasen, skal du lade hibernates session-fabrik beslutte at bruge den indbyggede sekvens (AUTO-INCREMENT) eller lade dvaletilstand bestemme (
GenerationType.AUTO
/GenerationType.IDENTITY
) hvor stort det åbne udvalg af reserverede PK'er er (Job of a DB-Architect). (Vi har omkring 20 servere til en database, så på en godt brugt tabel bruger vi en PK-distance på +100). Hvis kun én server har adgang til databasenGenerationType.TABLE
skal være korrekt.
Hibernate skal selv beregne det næste id ved hjælp af max(*)+1
men:
- Hvad hvis to anmodninger beder om
max(*)+1
på samme tid/med samme resultat? Til højre:Det sidste forsøg på atinsert
vil mislykkes.
Så du skal have en tabel LAST_IDS
i databasen, hvem gemmer de sidste tabel-PK'er. Hvis du kan lide at tilføje en, skal du udføre disse trin:
- Start læseoptimistisk transaktion.
- VÆLG MAX(adresse_id) FRA LAST_IDS
- gem maksimum i en java-variabel, dvs.:$OldID.
- $NewID =$OldID + 1. (+100 i pessimistisk lås)
- OPDATERING LAST_IDS SET address_id=
$newID
WHERE address_id=$oldID
? - begå den læseoptimistiske transaktion.
- hvis commit var vellykket, gem
$newID
tilsetID()
i HibernateBean, du kan lide at gemme. - Lad endelig Hibernate kalde indsættet.
Dette er den eneste måde, jeg ved det.
BTW:Hibernate-Entitys skal kun bruge nedarvning, hvis databasen understøtter nedarvning mellem tabeller som PostgreSQL
eller Oracle
.