web-dev-qa-db-fra.com

Génération automatique de clé primaire JPA

mon entité clé primaire ressemble ci-dessous

@GeneratedValue(strategy= GenerationType.TABLE)
private Long id;

quand je cours, je reçois une erreur

impossible d'obtenir ou de mettre à jour la valeur suivante; l'exception imbriquée est org.hibernate.exception.SQLGrammerException: impossible d'obtenir ou de mettre à jour la valeur suivante

mais quand je change

@GeneratedValue 
private Long id;

pas de jet d'erreur. Je veux générer une clé primaire unique par table sur Oracle db.

16
cometta

La @GeneratedValue(strategy=GenerationType.TABLE) indique au fournisseur JPA d'utiliser une table pour obtenir des ID lors de l'insertion d'entités nouvellement créées dans la base de données.

Lorsque vous utilisez Hibernate comme fournisseur, cela se traduira par une table hibernate_sequences qui comporte deux colonnes: le nom de l'entité et l'identité max déjà attribuée à cette entité. Ici, il semble qu'Hibernate ne réussisse pas à obtenir le prochain ID de celui-ci pour votre entité, mais il est difficile de dire exactement pourquoi, car vous n'avez pas fourni suffisamment d'informations pour cela.

Alors, pourriez-vous s'il vous plaît fournir le stacktrace complet? Veuillez également activer la journalisation avec hibernate.show_sql propriété définie sur true et définissez le niveau de journal approprié log4j.logger.org.hibernate.SQL=DEBUG. Joignez le journal à votre question si possible.

Peut-être vérifiez simplement que vous avez bien configuré le hibernate.dialect pour Oracle. En fait, joignez aussi votre configuration de mise en veille prolongée si possible.

PS: La façon "traditionnelle" de générer PK avec Oracle est d'utiliser des séquences (vous pouvez laisser Hibernate deviner la meilleure stratégie pour votre type de base de données en utilisant GenerationType.AUTO ou le forcer en utilisant SEQUENCE) mais je suppose que vous voulez que la structure de données résultante soit indépendante de la base de données. Sinon, je suggérerais plutôt de choisir des séquences.

EDIT: Répondre à un commentaire du PO sur GenerationType.AUTO. En effet, la valeur par défaut est une seule séquence globale appelée hibernate_sequence et cela pourrait être un problème. Mais, avec la configuration ci-dessous, vous pouvez utiliser GenerationType.AUTO et contrôle toujours le nom de la séquence pour les cas où la base de données utilise des séquences:

@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="my_entity_seq_gen")
@SequenceGenerator(name="my_entity_seq_gen", sequenceName="MY_ENTITY_SEQ")
private long id;

En d'autres termes, vous pouvez utiliser un nom de séquence différent pour chaque table sans perdre la portabilité.

29
Pascal Thivent

Il existe 4 stratégies pour la génération automatique dans JPA:

  • Auto
  • Identité
  • Séquence
  • Table

Pour l'annotation de clé primaire de génération automatique Oracle, Sequence et Table sont vos choix. La logique de base consiste à définir d'abord un générateur, utilisez @ SequenceGenerator ou @ TableGenerator respectivement, puis utilisez le générateur comme attribut dans @ GeneratedValue .

Voici un exemple d'utilisation de la stratégie de séquence:

  @Id
  @SequenceGenerator(name="SEQ_GEN", sequenceName="SEQ_JUST_FOR_TEST", allocationSize=1)
  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_GEN")
  private long id;

Voici un exemple d'utilisation de la stratégie de table:

  @Id
  @TableGenerator(name="TABLE_GEN",table="T_GENERATOR", pkColumnName = "GEN_KEY", pkColumnValue = "MONITOR2012.T_JUST_FOR_TEST", valueColumnName = "GEN_VALUE", initialValue = 1, allocationSize = 1 )
  @GeneratedValue(strategy = GenerationType.TABLE, generator="TABLE_GEN")
  private long id;

Si aucun générateur n'est spécifié dans l'annotation @ GeneratedValue , le choix sera laissé à l'implémentation JPA.

Si vous travaillez sur une base de données avec des tables existantes, assurez-vous que la séquence ou la table définie dans la base de données avant d'exécuter votre application. Le générateur de table aura également besoin que vous insériez une ligne dans la table avant que l'annotation @GeneratedValue puisse fonctionner correctement.

Voici un tutoriel sur comment configurer la génération automatique de clé primaire dans la base de données JPA pour Oracle .

9
Sheng.W