Hibernate's PostgreSQL dialekt není příliš jasný. Nezná vaše sekvence na SERIAL a předpokládá, že existuje globální sekvence pro celou databázi nazvaná „hibernate_sequence“, kterou může použít.
(AKTUALIZACE :Zdá se, že novější verze Hibernate mohou používat výchozí sekvence pro jednotlivé tabulky, když GenerationType.IDENTITY
je specifikováno. Otestujte svou verzi a použijte tuto namísto níže uvedeného, pokud vám to vyhovuje.)
Musíte změnit svá mapování tak, aby explicitně specifikovala každou sekvenci. Je to otravné, opakující se a zbytečné.
@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
je docela důležité. Pokud jej vynecháte, Hibernate bude slepě předpokládat, že sekvence je definována pomocí INCREMENT 50
takže když získá hodnotu ze sekvence, může tuto hodnotu použít a 49 hodnot pod ní jako jedinečné generované klíče. Pokud se vaše databázové sekvence zvýší o 1 – výchozí nastavení –, bude to mít za následek jedinečná porušení, protože se Hibernate pokouší znovu použít existující klíče.
Upozorňujeme, že získávání jednoho klíče po druhém bude výsledkem je další okružní cesta na vložku. Pokud mohu říci, Hibernate není schopen použít INSERT ... RETURNING
efektivně vracet vygenerované klíče, ani zřejmě nemůže používat rozhraní vygenerovaných klíčů JDBC. Pokud mu řeknete, aby použil sekvenci, zavolá nextval
pro získání hodnoty pak insert
což výslovně vede ke dvěma zpátečním letům. Chcete-li snížit náklady na to, můžete nastavit větší přírůstek u sekvencí kláves se spoustou vložek a nezapomeňte jej nastavit na mapování a základní posloupnost databáze. To způsobí, že Hibernate zavolá nextval
méně často a ukládat bloky klíčů do mezipaměti, abyste je mohli rozdávat, jak to jde.
Jsem si jistý, že z výše uvedeného vidíte, že nesouhlasím se zde provedenými návrhy Hibernate, alespoň z pohledu použití s PostgreSQL. Měli by používat getGeneratedKeys
nebo pomocí INSERT ... RETURNING
s DEFAULT
pro klíč, nechat databázi, aby se o to postarala, aniž by se Hibernate musela sama trápit s názvy sekvencí nebo s explicitním přístupem k nim.
BTW, pokud používáte Hibernate s Pg, možná budete chtít také spouštěč oplock pro Pg, který umožní optimistickému zamykání Hibernate bezpečně spolupracovat s normálním zamykáním databáze. Bez něj nebo něčeho podobného budou mít vaše aktualizace Hibernate tendenci blokovat změny provedené prostřednictvím jiných běžných klientů SQL. Zeptejte se mě, jak to vím.