J'ai une configuration avec Oracle Xe 10G, Hibernate 3.5, JPA 2.0. Il existe une table simple avec une clé primaire, générée par un déclencheur de base de données à l'insertion. La gâchette obtient la valeur d'une séquence. La construction de la gâchette / séquence a été faite par Oracle Xe.
La question réelle est la suivante: comment puis-je obtenir la valeur actuelle de l'ID dans mon entité après une entitémanager.persiste? -> id est -> id est -> échoue car hibernate tente d'interroger la séquence d'une séquence (qui n'existe pas). P> IDS sont générés dans la base de données dans les deux premières approches, mais je n'ai pas la valeur dans mon objet em>. p> p>
J'ai essayé: p> 0 code>; p>
0 code>; p>
3 Réponses :
sauf si vous êtes lié à la gâchette, cela ressemble à un niveau d'obscurcissement sur la séquence, et il semble aller à l'extérieur du cycle de vie habituel de l'hibernate. Pourquoi ne pas appeler directement la séquence: alors vous obtiendrez la valeur en arrière, car Hibernate est directement impliqué dans la génération, et il n'y a pas quelque chose qui ne se passe pas après le fait. P> p>
Merci, mais: la truc de déclenchement est la façon Oracle de générer automatiquement des valeurs PK incrémentées. Si je me débarrasse de cela, je perdrai la possibilité d'insérer facilement des rangées avec des requêtes directes sur la base de données. Et deuxièmement, si j'interne comme dans votre suggestion, je ne peux pas passer facilement à Derby pour des tests d'unité: (... ce dont j'ai besoin est une annotation qui dit: "Prenez simplement ce que la DB a généré".
Googled Ce point et basé sur un examen superficiel, il apparaît que d'autres utilisateurs ont eu le succès des séquences Oracle de Hibernate. Voici un exemple: forum.hibernate.org/viewtopic.php?p=2442821. Sur la question Derby, les tests unitaires contre une plate-forme DB différente de votre plate-forme de déploiement ne sont pas une meilleure pratique et pourraient conduire à des incohérences entre test unitaire et comportement d'exécution.
@Mulmoth: Sauf si un autre champ identifie de manière unique la ligne, comment hiberniserait-il pour obtenir l'identifiant généré de la base de données, car le seul moyen d'identifier la ligne qui vient d'être inséré est son identifiant, qu'il ne sait pas . En bref, l'identifiant est nécessaire pour obtenir l'identifiant. Votre déclencheur est une très mauvaise idée.
Vous pouvez échanger la clé générée par la DB dans la session Oracle. Pour cela, le déclencheur d'insertion doit appeler à partir de votre code, vous pouvez récupérer la nouvelle valeur de la clé avec la requête p> il est important d'utiliser la même instance d'entitémanager pour persister la nouvelle entité et récupérer la valeur clé générée. P> P>
Contrairement aux commentaires de @JB NIZET, je peux réellement penser à de nombreuses raisons pour lesquelles nous laisserions un identifiant d'attribution de déclenchement: exécution des PROC stockés, exécution manuelle de SQLS et des requêtes natives en cours d'hibernate, juste pour nommer quelques-uns. J'ai personnellement trouvé la solution suivante assez satisfaisante. Il permet d'hiberner trouver l'identifiant max et l'avoir incrémenté à chaque fois qu'une instruction insertion est appelée. Mais lorsque l'instruction frappe la base de données, l'ID est ignoré et remplacé par celui généré par la gâchette, il n'y a donc pas de Unicité dans un problème de cluster : P>
@Id @GeneratedValue(generator="increment") @GenericGenerator(name="increment", strategy = "increment") private Long id;
S'il vous plaît jeter un oeil à cet exemple:
Pour moi, l'ID de retour 94 après persistez lorsque l'identifiant réel dans la base de données créée par le déclencheur était de 90.