Como escolher a estratégia de geração de id ao usar JPA e Hibernate

102

Eu estava passando pela seção de geração de Id do guia de referência do Hibernate e "persistência de java com Hibernate"

Existem algumas opções disponíveis com Hibernate e JPA combinados.

Eu estava procurando uma documentação adicional sobre como escolher a estratégia específica de geração de id.

Também estou procurando pontos de inflexão.

Por exemplo, a estratégia hilo deve reduzir a contenção. Estou assumindo que deve haver uma compensação associada a essa escolha.

Quero ser educado sobre as trocas.

Existe alguma literatura disponível?

Vlad Mihalcea
fonte

Respostas:

92

O API Doc é muito claro sobre isso.

Todos os geradores implementam a interface org.hibernate.id.IdentifierGenerator. Esta é uma interface muito simples. Alguns aplicativos podem optar por fornecer suas próprias implementações especializadas, no entanto, o Hibernate fornece uma variedade de implementações integradas. Os nomes de atalho para os geradores integrados são os seguintes:

incremento

gera identificadores do tipo long, short ou int que são únicos apenas quando nenhum outro processo está inserindo dados na mesma tabela. Não use em um cluster.

identidade

suporta colunas de identidade em DB2, MySQL, MS SQL Server, Sybase e HypersonicSQL. O identificador retornado é do tipo long, short ou int.

seqüência

usa uma sequência em DB2, PostgreSQL, Oracle, SAP DB, McKoi ou um gerador em Interbase. O identificador retornado é do tipo long, short ou int

hilo

usa um algoritmo hi / lo para gerar com eficiência identificadores do tipo long, short ou int, dadas uma tabela e coluna (por padrão hibernate_unique_key e next_hi respectivamente) como uma fonte de valores hi. O algoritmo hi / lo gera identificadores que são exclusivos apenas para um banco de dados específico.

seqhilo

usa um algoritmo hi / lo para gerar identificadores do tipo long, short ou int de maneira eficiente, dada uma sequência de banco de dados nomeada.

uuid

usa um algoritmo UUID de 128 bits para gerar identificadores do tipo string que são exclusivos em uma rede (o endereço IP é usado). O UUID é codificado como uma string de 32 dígitos hexadecimais de comprimento.

guid

usa uma string GUID gerada pelo banco de dados no MS SQL Server e MySQL.

nativo

seleciona identidade, sequência ou hilo dependendo das capacidades do banco de dados subjacente.

atribuído

permite que o aplicativo atribua um identificador ao objeto antes que save () seja chamado. Esta é a estratégia padrão se nenhum elemento for especificado.

selecionar

recupera uma chave primária, atribuída por um disparador de banco de dados, selecionando a linha por alguma chave única e recuperando o valor da chave primária.

estrangeiro

usa o identificador de outro objeto associado. Geralmente é usado em conjunto com uma associação de chave primária.

identidade de sequência

uma estratégia de geração de sequência especializada que utiliza uma sequência de banco de dados para a geração de valor real, mas combina isso com JDBC3 getGeneratedKeys para retornar o valor do identificador gerado como parte da execução da instrução de inserção. Essa estratégia é compatível apenas com drivers Oracle 10g direcionados para JDK 1.4. Os comentários sobre essas instruções de inserção estão desabilitados devido a um bug nos drivers Oracle.

Se você está construindo um aplicativo simples com poucos usuários simultâneos, você pode ir para incremento, identidade, hilo etc. Eles são simples de configurar e não precisam de muita codificação dentro do banco de dados.

Você deve escolher a sequência ou guid dependendo do seu banco de dados. São seguros e melhores porque a idgeração acontecerá dentro do banco de dados.

Atualização: Recentemente, tivemos um problema com idendity onde o tipo primitivo (int) foi corrigido usando o tipo warapper (Integer).

ManuPK
fonte
Muito obrigado pela sua resposta. Já olhei os documentos. No entanto, estou procurando por que as pessoas usariam algo como hilo e seqhilo. Quando fazemos essa escolha. Quais são os casos de uso para select.
Quando há algo tão direto como sequência ou guia, o que pode exigir que o desenvolvedor escolha outros caminhos.
1
Eu atualizei minha resposta. Na verdade , incremento, identidade, hilo etc. são mais simples. mas eles não são adequados para aplicativos corporativos. Manter todas as opções não é um problema, mas certifique-se de usar a mais adequada para você!
ManuPK
Sim. Até agora, não tive o privilégio de votar positivamente ou aceitar.
Estou olhando para mergulhar em mais detalhes, se você tiver tempo, me avise.
45

Basicamente, você tem duas opções principais:

  • Você mesmo pode gerar o identificador e, nesse caso, pode usar um identificador atribuído .
  • Você pode usar a @GeneratedValueanotação e o Hibernate irá atribuir o identificador para você.

Para os identificadores gerados, você tem duas opções:

Para identificadores numéricos, você tem três opções :

  • IDENTIDADE
  • SEQÜÊNCIA
  • TABELA

IDENTITY é apenas uma boa escolha quando você não pode usar SEQUENCE (por exemplo, MySQL) porque desativa as atualizações em lote do JDBC .

SEQUENCE é a opção preferida, especialmente quando usada com um otimizador de identificador como pooled ou pooled-lo .

TABLE deve ser evitado a qualquer custo, uma vez que usa uma transação separada para buscar o identificador e bloqueios de nível de linha que escalam mal.

Vlad Mihalcea
fonte
20


Há algum tempo, escrevi um artigo detalhado sobre os geradores de chaves do Hibernate: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Escolher o gerador correto é uma tarefa complicada, mas é importante tentar acertar o mais rápido possível - uma migração tardia pode ser um pesadelo.

Um pouco fora do assunto, mas uma boa chance de levantar um ponto geralmente esquecido que é o compartilhamento de chaves entre aplicativos (via API). Pessoalmente, sempre prefiro as surrogate keys e se eu precisar comunicar meus objetos com outros sistemas, não exponho minha chave (mesmo que seja uma substituta) - eu uso uma 'chave externa' adicional. Como consultor, vi mais de uma vez 'ótimas' integrações de sistema usando chaves de objeto (a abordagem 'está lá, vamos apenas usá-lo') apenas para descobrir um ou dois anos depois que um lado tem problemas com o intervalo de chaves ou algo de o tipo que requer uma migração profunda no sistema, expondo suas chaves internas. Expor sua chave significa expor um aspecto fundamental de seu código a restrições externas às quais não deveria ser exposto.

Eyal Lupu
fonte
2

Acho esta palestra muito valiosa https://vimeo.com/190275665 , no ponto 3 ela resume esses geradores e também dá algumas análises de desempenho e orientação quando você usa cada um.

Adelin
fonte
6
Esse vídeo parece muito familiar.
Vlad Mihalcea