Dialekt PostgreSQL w Hibernate nie jest zbyt jasny. Nie wie o twoich sekwencjach dla poszczególnych serii i zakłada, że istnieje globalna sekwencja w całej bazie danych o nazwie „hibernate_sequence”, której może użyć.
(AKTUALIZUJ :Wygląda na to, że nowsze wersje Hibernate mogą używać domyślnych sekwencji dla tabeli, gdy GenerationType.IDENTITY
jest specyficzne. Przetestuj swoją wersję i użyj tego zamiast poniższego, jeśli działa dla Ciebie.)
Musisz zmienić swoje mapowania, aby wyraźnie określić każdą sekwencję. To denerwujące, powtarzalne i bezcelowe.
@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {
private static final long serialVersionUID = -7049957706738879274L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="judgements_id_seq")
@SequenceGenerator(name="judgements_id_seq", sequenceName="judgements_id_seq", allocationSize=1)
@Column(name = "JUD_ID")
private Long _judId;
...
allocationSize=1
jest bardzo ważne. Jeśli go pominiesz, Hibernate ślepo założy, że sekwencja jest zdefiniowana za pomocą INCREMENT 50
więc gdy otrzyma wartość z sekwencji, może użyć tej wartości i 49 wartości pod nią jako unikalne wygenerowane klucze. Jeśli sekwencje w Twojej bazie danych zwiększają się o 1 — wartość domyślna — spowoduje to unikalne naruszenia, ponieważ Hibernate będzie próbował ponownie użyć istniejących kluczy.
Pamiętaj, że uzyskanie jednego klucza naraz będzie skutkować dodatkową podróżą w obie strony na wkładkę. O ile wiem, Hibernate nie jest w stanie użyć INSERT ... RETURNING
skutecznie zwracać wygenerowane klucze, ani najwyraźniej nie może używać interfejsu wygenerowanych kluczy JDBC. Jeśli powiesz mu, aby używał sekwencji, wywoła nextval
aby uzyskać wartość, a następnie insert
to wyraźnie, co skutkuje dwiema podróżami w obie strony. Aby zmniejszyć ten koszt, możesz ustawić większy przyrost w sekwencjach klawiszy z dużą ilością wstawek , pamiętając o ustawieniu tego w mapowaniu i podstawowa sekwencja bazy danych. To spowoduje, że Hibernate wywoła nextval
rzadziej i bloki kluczy w pamięci podręcznej do rozdawania w miarę postępu.
Na pewno widać z powyższego, że nie zgadzam się z dokonanymi tutaj wyborami projektowymi Hibernate, przynajmniej z perspektywy używania go z PostgreSQL. Powinni używać getGeneratedKeys
lub używając INSERT ... RETURNING
z DEFAULT
dla klucza, pozwalając bazie danych zająć się tym bez konieczności zajmowania się przez Hibernate nazwami sekwencji lub jawnym dostępem do nich.
BTW, jeśli używasz Hibernate z Pg, prawdopodobnie będziesz potrzebować wyzwalacza opozycji dla Pg, aby umożliwić optymistycznemu blokowaniu Hibernate bezpieczną interakcję z normalnym blokowaniem bazy danych. Bez tego lub czegoś podobnego twoje aktualizacje Hibernate będą miały tendencję do blokowania zmian dokonywanych za pośrednictwem innych zwykłych klientów SQL. Zapytaj mnie, skąd wiem.