Wszyscy znamy domyślne zachowanie Hibernate'a podczas używania @SequenceGenerator
- zwiększa rzeczywistą sekwencję bazy danych o jeden , pomnóż tę wartość o 50 ( allocationSize
wartość domyślna ) - a następnie używa tej wartości jako identyfikatora jednostki.
Jest to nieprawidłowe zachowanie i sprzeczne ze specyfikacją, która mówi:
ocationSize - (opcjonalne) kwota do zwiększenia podczas przydzielania numerów sekwencyjnych z sekwencji.
Żeby było jasne: nie przejmuję się lukami między wygenerowanymi identyfikatorami.
Zależy mi na identyfikatorach, które nie są zgodne z sekwencją bazową bazy danych. Na przykład: każda inna aplikacja (która np. Używa zwykłego JDBC) może chcieć wstawić nowe wiersze pod identyfikatorami uzyskanymi z sekwencji - ale wszystkie te wartości mogą być już wykorzystane przez Hibernate! Szaleństwo.
Czy ktoś zna jakieś rozwiązanie tego problemu (bez ustawiania, allocationSize=1
a tym samym obniżania wydajności)?
EDYCJA:
Aby wszystko było jasne. Jeśli ostatni wstawiony rekord miał ID = 1
, to HB użyje wartości 51, 52, 53...
dla swoich nowych jednostek, ALE w tym samym czasie: wartość sekwencji w bazie danych zostanie ustawiona na 2
. Co może łatwo prowadzić do błędów, gdy inne aplikacje używają tej sekwencji.
Z drugiej strony: specyfikacja mówi (w moim rozumieniu), że sekwencja bazy danych powinna była być ustawiona na, 51
a tymczasem HB powinien używać wartości z zakresu 2, 3 ... 50
AKTUALIZACJA:
Jak Steve Ebersole wspomniał poniżej: zachowanie opisane przeze mnie (a także najbardziej intuicyjne dla wielu) można włączyć, ustawiając hibernate.id.new_generator_mappings=true
.
Dziękuję wam wszystkim.
UPDATE 2:
Dla przyszłych czytelników poniżej znajduje się działający przykład.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
@SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
private Long id;
}
persistence.xml
<persistence-unit name="testPU">
<properties>
<property name="hibernate.id.new_generator_mappings" value="true" />
</properties>
</persistence-unit>
save
musi zapytać bazę danych o następną wartość sekwencji.
SequenceGenerator
Hibernate będzie wysyłać zapytania do bazy danych tylko wtedy, gdy allocationsize
skończy się ilość identyfikatorów określonych przez . Jeśli to skonfigurujesz, allocationSize = 1
to jest to powód, dla którego Hibernacja wysyła zapytanie do DB dla każdej wstawki. Zmień tę wartość i gotowe.
hibernate.id.new_generator_mappings
ustawienie jest naprawdę ważne. Mam nadzieję, że jest to ustawienie domyślne, że nie muszę spędzać tyle czasu na badaniu, dlaczego numer id zwariował.