PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

o hibernate não conseguiu obter o próximo valor da sequência


O dialeto PostgreSQL do Hibernate não é muito brilhante. Ele não sabe sobre suas sequências por SERIAL e está assumindo que há uma sequência global em todo o banco de dados chamada "hibernate_sequence" que ele pode usar.

(ATUALIZAÇÃO :Parece que as versões mais recentes do Hibernate podem usar as sequências padrão por tabela quando GenerationType.IDENTITY é especificado. Teste sua versão e use isso em vez do abaixo se funcionar para você.)

Você precisa alterar seus mapeamentos para especificar explicitamente cada sequência. É chato, repetitivo e inútil.
@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;
...

O allocationSize=1 é bastante importante. Se você omitir, o Hibernate assumirá cegamente que a sequência está definida com INCREMENT 50 então, quando ele obtém um valor de uma sequência, ele pode usar esse valor e os 49 valores abaixo dele como chaves geradas exclusivas. Se as sequências do seu banco de dados aumentarem em 1 - o padrão - isso resultará em violações exclusivas, pois o Hibernate tenta reutilizar as chaves existentes.

Observe que obter uma chave de cada vez vai resultar em uma viagem de ida e volta adicional por pastilha. Até onde eu sei, o Hibernate não é capaz de usar INSERT ... RETURNING para retornar chaves geradas com eficiência, nem aparentemente pode usar a interface de chaves geradas por JDBC. Se você disser para usar uma sequência, ele chamará nextval para obter o valor, insert isso explicitamente, resultando em duas viagens de ida e volta. Para reduzir o custo disso, você pode definir um incremento maior nas sequências de teclas com muitas inserções, lembrando de defini-lo no mapeamento e a seqüência de banco de dados subjacente. Isso fará com que o Hibernate chame nextval com menos frequência e blocos de chaves em cache para distribuir à medida que avança.

Tenho certeza que você pode ver acima que não concordo com as escolhas de design do Hibernate feitas aqui, pelo menos da perspectiva de usá-lo com o PostgreSQL. Eles devem estar usando getGeneratedKeys ou usando INSERT ... RETURNING com DEFAULT para a chave, deixando o banco de dados cuidar disso sem que o Hibernate tenha que se preocupar com os nomes das sequências ou acesso explícito a elas.

BTW, se você estiver usando o Hibernate com Pg, possivelmente também desejará um gatilho oplock para Pg para permitir que o bloqueio otimista do Hibernate interaja com segurança com o bloqueio normal do banco de dados. Sem ele ou algo parecido, suas atualizações do Hibernate tenderão a atrapalhar as alterações feitas por meio de outros clientes SQL regulares. Pergunte-me como eu sei.