sql >> Databáze >  >> RDS >> PostgreSQL

Hibernate nemohl získat hodnotu další sekvence

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.



  1. Funkce dynamického dotazování Postgres

  2. Osvědčený postup:Import souboru mySQL do PHP; rozdělené dotazy

  3. Operátor zřetězení řetězců v Oracle, Postgres a SQL Server

  4. Jak mohu procházet sadu výsledků MySQL více než jednou pomocí funkcí mysql_*?