Jak wybrać strategię generowania identyfikatora podczas korzystania z JPA i Hibernate

102

Przeglądałem sekcję dotyczącą generowania identyfikatorów w przewodniku po Hibernate i „Trwałość języka Java w Hibernate”

Istnieje wiele opcji dostępnych w połączeniu z Hibernate i JPA.

Szukałem dalszej dokumentacji, jak wybrać konkretną strategię generowania identyfikatorów.

Szukam też punktów zwrotnych.

Na przykład oczekuje się, że strategia hilo zmniejszy rywalizację. Zakładam, że z tym wyborem musi wiązać się kompromis.

Chcę być poinformowany o kompromisach.

Czy jest dostępna literatura?

Vlad Mihalcea
źródło

Odpowiedzi:

92

Dokumentacja API jest bardzo jasna na ten temat.

Wszystkie generatory implementują interfejs org.hibernate.id.IdentifierGenerator. To bardzo prosty interfejs. Niektóre aplikacje mogą udostępniać własne wyspecjalizowane implementacje, jednak Hibernate udostępnia szereg wbudowanych implementacji. Nazwy skrótów dla wbudowanych generatorów są następujące:

przyrost

generuje identyfikatory typu long, short lub int, które są unikalne tylko wtedy, gdy żaden inny proces nie wstawia danych do tej samej tabeli. Nie używaj w klastrze.

tożsamość

obsługuje kolumny tożsamości w DB2, MySQL, MS SQL Server, Sybase i HypersonicSQL. Zwrócony identyfikator jest typu long, short lub int.

sekwencja

używa sekwencji w DB2, PostgreSQL, Oracle, SAP DB, McKoi lub generatorze w Interbase. Zwrócony identyfikator jest typu long, short lub int

hilo

używa algorytmu hi / lo do wydajnego generowania identyfikatorów typu long, short lub int, biorąc pod uwagę tabelę i kolumnę (domyślnie odpowiednio hibernate_unique_key i next_hi) jako źródło wartości hi. Algorytm hi / lo generuje identyfikatory, które są unikalne tylko dla określonej bazy danych.

seqhilo

używa algorytmu hi / lo do wydajnego generowania identyfikatorów typu long, short lub int, na podstawie nazwanej sekwencji bazy danych.

uuid

używa 128-bitowego algorytmu UUID do generowania identyfikatorów typu string, które są unikalne w sieci (używany jest adres IP). Identyfikator UUID jest zakodowany jako ciąg o długości 32 cyfr szesnastkowych.

guid

używa ciągu GUID wygenerowanego przez bazę danych na MS SQL Server i MySQL.

ojczysty

wybiera tożsamość, sekwencję lub hilo w zależności od możliwości bazowej bazy danych.

przydzielony

pozwala aplikacji przypisać identyfikator do obiektu przed wywołaniem metody save (). Jest to strategia domyślna, jeśli nie określono żadnego elementu.

Wybierz

pobiera klucz podstawowy przypisany przez wyzwalacz bazy danych, wybierając wiersz za pomocą jakiegoś unikalnego klucza i pobierając wartość klucza podstawowego.

obcy

używa identyfikatora innego powiązanego obiektu. Zwykle jest używany w połączeniu z skojarzeniem klucza podstawowego.

identyczność sekwencji

wyspecjalizowana strategia generowania sekwencji, która wykorzystuje sekwencję bazy danych do rzeczywistego generowania wartości, ale łączy ją z JDBC3 getGeneratedKeys, aby zwrócić wygenerowaną wartość identyfikatora w ramach wykonywania instrukcji insert. Ta strategia jest obsługiwana tylko w sterownikach Oracle 10g przeznaczonych dla JDK 1.4. Komentarze do tych instrukcji wstawiania są wyłączone z powodu błędu w sterownikach Oracle.

Jeśli budujesz prostą aplikację z niewielką liczbą jednoczesnych użytkowników, możesz przejść do inkrementacji, tożsamości, hilo itp. Są one proste w konfiguracji i nie wymagały wiele kodowania wewnątrz bazy danych.

W zależności od bazy danych należy wybrać sekwencję lub guid . Są one bezpieczne i lepsze, ponieważ idgenerowanie będzie odbywać się w bazie danych.

Aktualizacja: Ostatnio mieliśmy problem z identyfikacją polegający na tym, że typ prymitywny (int) został naprawiony przez użycie typu warapper (Integer).

ManuPK
źródło
Dziękuję bardzo za odpowiedź. Patrzyłem już na doktorów. Jednak szukam, dlaczego ludzie mieliby używać czegoś takiego jak hilo i seqhilo. Kiedy dokonamy tego wyboru. Jakie są przypadki użycia Select.
Kiedy istnieje coś tak prostego, jak sekwencja lub przewodnik, co może wymagać od dewelopera wyboru innych ścieżek.
1
Zaktualizowałem moją odpowiedź. W rzeczywistości przyrost, tożsamość, hilo itp. Są prostsze. ale nie nadają się do zastosowań korporacyjnych. Zachowanie wszystkich opcji nie stanowi problemu, ale upewnij się, że używasz najlepiej dopasowanej dla siebie!
ManuPK
Tak. Jak dotąd nie miałem przywileju głosowania za ani akceptacji.
Chciałbym zagłębić się w więcej szczegółów, jeśli masz czas, daj mi znać.
45

Zasadniczo masz dwie główne możliwości:

  • Możesz samodzielnie wygenerować identyfikator, w takim przypadku możesz użyć przypisanego identyfikatora .
  • Możesz skorzystać z @GeneratedValueadnotacji, a Hibernate przydzieli Ci identyfikator.

W przypadku wygenerowanych identyfikatorów masz dwie możliwości:

W przypadku identyfikatorów numerycznych masz trzy opcje :

  • TOŻSAMOŚĆ
  • SEKWENCJA
  • STÓŁ

TOŻSAMOŚĆ jest dobrym wyborem tylko wtedy, gdy nie możesz użyć SEQUENCE (np. MySQL), ponieważ wyłącza ona aktualizacje wsadowe JDBC .

SEQUENCE jest preferowaną opcją, zwłaszcza gdy jest używana z optymalizatorem identyfikatorów, takim jak pooled lub pooled-lo .

TABELI należy unikać za wszelką cenę, ponieważ wykorzystuje on oddzielną transakcję do pobrania identyfikatora i blokad na poziomie wiersza, które są słabo skalowane.

Vlad Mihalcea
źródło
20


Jakiś czas temu napisałem szczegółowy artykuł o generatorach kluczy Hibernate: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Wybór odpowiedniego generatora jest skomplikowanym zadaniem, ale ważne jest, aby spróbować jak najszybciej go naprawić - późna migracja może być koszmarem.

Trochę poza tematem, ale dobra okazja, aby poruszyć kwestię zwykle pomijaną, czyli współdzielenie kluczy między aplikacjami (przez API). Osobiście zawsze wolę klucze zastępcze i jeśli muszę komunikować się z obiektami innymi systemami, nie ujawniam swojego klucza (nawet jeśli jest to klucz zastępczy) - używam dodatkowego „klucza zewnętrznego”. Jako konsultant widziałem wiele razy „świetne” integracje systemów z użyciem kluczy obiektowych (podejście „jest tam, użyjmy tego”) tylko po to, by po roku lub dwóch stwierdzić, że jedna ze stron ma problemy z zakresem kluczy lub czymś podobnym rodzaj wymagający głębokiej migracji w systemie, odsłaniając jego klucze wewnętrzne. Ujawnienie klucza oznacza wystawienie podstawowego aspektu kodu na zewnętrzne ograniczenia, na które tak naprawdę nie należy narażać.

Eyal Lupu
źródło
2

Uważam, że ten wykład jest bardzo cenny https://vimeo.com/190275665 , w punkcie 3 podsumowuje on te generatory, a także podaje analizę wydajności i wskazówki, gdy używasz każdego z nich.

Adelin
źródło
6
Ten film wygląda bardzo znajomo.
Vlad Mihalcea,