Comment choisir la stratégie de génération d'identifiant lors de l'utilisation de JPA et Hibernate

102

J'étais en train de parcourir la section de génération d'identifiant du guide de référence Hibernate et "java persistence with Hibernate"

Il existe de nombreuses options disponibles avec Hibernate et JPA combinés.

Je cherchais une documentation supplémentaire sur la façon de choisir la stratégie de génération d'identifiant spécifique.

Je recherche également des points de basculement.

Par exemple, la stratégie hilo devrait réduire les conflits. Je suppose qu'il doit y avoir un compromis associé à ce choix.

Je veux être informé des compromis.

Existe-t-il de la documentation disponible?

Vlad Mihalcea
la source

Réponses:

92

Le Doc API est très clair à ce sujet.

Tous les générateurs implémentent l'interface org.hibernate.id.IdentifierGenerator. C'est une interface très simple. Certaines applications peuvent choisir de fournir leurs propres implémentations spécialisées, cependant, Hibernate fournit une gamme d'implémentations intégrées. Les noms de raccourcis pour les générateurs intégrés sont les suivants:

incrément

génère des identifiants de type long, short ou int qui sont uniques uniquement lorsqu'aucun autre processus n'insère de données dans la même table. Ne pas utiliser dans un cluster.

identité

prend en charge les colonnes d'identité dans DB2, MySQL, MS SQL Server, Sybase et HypersonicSQL. L'identifiant renvoyé est de type long, short ou int.

séquence

utilise une séquence dans DB2, PostgreSQL, Oracle, SAP DB, McKoi ou un générateur dans Interbase. L'identifiant retourné est de type long, short ou int

hilo

utilise un algorithme hi / lo pour générer efficacement des identifiants de type long, short ou int, à partir d'une table et d'une colonne (par défaut hibernate_unique_key et next_hi respectivement) comme source de valeurs hi. L'algorithme hi / lo génère des identificateurs uniques uniquement pour une base de données particulière.

seqhilo

utilise un algorithme hi / lo pour générer efficacement des identificateurs de type long, short ou int, étant donné une séquence de base de données nommée.

uuid

utilise un algorithme UUID 128 bits pour générer des identifiants de type chaîne qui sont uniques au sein d'un réseau (l'adresse IP est utilisée). L'UUID est codé sous la forme d'une chaîne de 32 chiffres hexadécimaux de longueur.

guid

utilise une chaîne GUID générée par la base de données sur MS SQL Server et MySQL.

originaire de

sélectionne l'identité, la séquence ou le hilo en fonction des capacités de la base de données sous-jacente.

attribué

permet à l'application d'affecter un identifiant à l'objet avant l'appel de save (). Il s'agit de la stratégie par défaut si aucun élément n'est spécifié.

sélectionner

récupère une clé primaire, attribuée par un déclencheur de base de données, en sélectionnant la ligne par une clé unique et en récupérant la valeur de la clé primaire.

étranger

utilise l'identifiant d'un autre objet associé. Il est généralement utilisé en conjonction avec une association de clé primaire.

identité de séquence

une stratégie de génération de séquence spécialisée qui utilise une séquence de base de données pour la génération de valeur réelle, mais la combine avec JDBC3 getGeneratedKeys pour renvoyer la valeur d'identificateur générée dans le cadre de l'exécution de l'instruction d'insertion. Cette stratégie n'est prise en charge que sur les pilotes Oracle 10g ciblés pour JDK 1.4. Les commentaires sur ces instructions d'insertion sont désactivés en raison d'un bogue dans les pilotes Oracle.

Si vous construisez une application simple avec peu d'utilisateurs simultanés, vous pouvez opter pour l' incrémentation, l'identité, hilo etc. Ceux-ci sont simples à configurer et n'ont pas besoin de beaucoup de codage dans la base de données.

Vous devez choisir la séquence ou le guid en fonction de votre base de données. Ceux-ci sont sûrs et meilleurs car la idgénération se fera à l'intérieur de la base de données.

Mise à jour: Récemment, nous avons eu un problème avec l'identité où le type primitif (int) a été corrigé en utilisant le type warapper (Integer) à la place.

ManuPK
la source
Merci beaucoup pour votre réponse. J'ai déjà regardé les documents. Cependant, je cherche pourquoi les gens utiliseraient quelque chose comme hilo et seqhilo. Quand faisons-nous ce choix. Quels sont les cas d'utilisation de select.
Quand il y a quelque chose d'aussi simple qu'une séquence ou un guide, ce qui peut obliger le développeur à choisir d'autres voies.
1
J'ai mis à jour ma réponse. En fait, l' incrémentation, l'identité, le hilo etc. sont plus simples. mais ils ne conviennent pas aux applications d'entreprise. Garder toutes les options n'est pas un problème, mais assurez-vous d'utiliser celle qui vous convient le mieux!
ManuPK
Ouais. Jusqu'à présent, je n'ai pas eu le privilège de voter pour ou d'accepter.
Je cherche à plonger dans plus de détails, si vous avez le temps, faites-le moi savoir.
45

En gros, vous avez deux choix majeurs:

  • Vous pouvez générer vous-même l'identifiant, auquel cas vous pouvez utiliser un identifiant attribué .
  • Vous pouvez utiliser l' @GeneratedValueannotation et Hibernate attribuera l'identifiant pour vous.

Pour les identifiants générés, vous avez deux options:

Pour les identifiants numériques, vous avez trois options :

  • IDENTITÉ
  • SÉQUENCE
  • TABLE

IDENTITY n'est un bon choix que lorsque vous ne pouvez pas utiliser SEQUENCE (par exemple MySQL) car il désactive les mises à jour par lots JDBC .

SEQUENCE est l'option préférée, en particulier lorsqu'elle est utilisée avec un optimiseur d'identifiant tel que pooled ou pooled-lo .

TABLE est à éviter à tout prix car il utilise une transaction distincte pour récupérer l'identifiant et les verrous au niveau des lignes qui évoluent mal.

Vlad Mihalcea
la source
20


Il y a quelque temps, j'ai écrit un article détaillé sur les générateurs de clés Hibernate: http://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

Choisir le bon générateur est une tâche compliquée, mais il est important d'essayer de bien faire les choses dès que possible - une migration tardive peut être un cauchemar.

Un peu hors sujet mais une bonne chance de soulever un point généralement négligé qui est le partage de clés entre applications (via API). Personnellement, je préfère toujours les clés de substitution et si je dois communiquer mes objets avec d'autres systèmes, je n'expose pas ma clé (même si c'est une clé de substitution) - j'utilise une «clé externe» supplémentaire. En tant que consultant, j'ai vu plus d'une fois de `` grandes '' intégrations de système utilisant des clés d'objet (l'approche `` c'est là, utilisons-la '') juste pour trouver un an ou deux plus tard qu'un côté a des problèmes avec la plage de clés ou quelque chose de le genre nécessitant une migration profonde sur le système exposant ses clés internes. Exposer votre clé signifie exposer un aspect fondamental de votre code à des contraintes externes ne devrait pas vraiment être exposé.

Eyal Lupu
la source
2

Je trouve cette conférence très précieuse https://vimeo.com/190275665 , au point 3, elle résume ces générateurs et donne également une analyse des performances et des lignes directrices lorsque vous utilisez chacun d'eux.

Adelin
la source
6
Cette vidéo semble très familière.
Vlad Mihalcea