7
votes

Hibernate + "sur la clé en double" logique

Je cherche un moyen de enregistrer ou mettre à jour enregistrements, en fonction de la clé unique de la table composée de plusieurs colonnes).

Je veux atteindre la même fonctionnalité utilisée par insert ... sur la mise à jour de la clé en double - SIGNIFIQUE Pour enregistrer aveuglément, insérez le DB / Hibernate Insérer un nouveau, ou mettez à jour le fichier existant. un si la clé unique existe déjà.

Je sais que je peux utiliser @sqlinsert (sql = "insert dans .. sur la mise à jour des touches en double") , mais j'espérais ne pas écrire mes propres SQLS et laisser hiberner faire le travail. (Je suppose que cela fera un meilleur travail - sinon pourquoi utiliser hibernate?)


2 commentaires

Vos probablement mieux avec la route des touches dup ...


Je pense que je vais vraiment rester avec la clé DUP pour l'instant ...


3 Réponses :


1
votes

Cela ne sonne pas vraiment comme une approche propre pour moi. Il serait préférable de voir d'abord si une entité avec une clé (s) donnée (s) existe (s). Si oui, mettez-le à la mettre à jour et enregistrez-le, sinon en créer un nouveau.

Edit

ou peut-être considérer si fusion () est ce que vous recherchez:

  • S'il y a une instance persistante avec le même identifiant actuellement associé à la session, copiez l'état de l'objet donné sur l'instance persistante
  • S'il n'y a pas d'instance persistante actuellement associée à la session, essayez de le charger dans la base de données ou de créer une nouvelle instance persistante
  • L'instance persistante est renvoyée
  • L'instance donnée ne s'applique pas à la session, elle reste détachée

    << a href = "http://docs.jboss.org/ibernate/core/3.3/Reference/fr/html/ObjectState.html" rel = "nofollow"> http://docs.jboss.org /hibernate/core/3.3/Reference/fr/html/ObjectState.html


5 commentaires

Je ne suis pas sûr que la DB elle-même aurait également besoin de vérifier l'existence de la ligne d'abord avant de mettre à jour / insérer lorsque vous utilisez «sur la clé en double».


En outre, je ne sais pas si sur la touche dupliquée est pris en charge par tous les serveurs DB (comme MS-SQL).


Je pense que la DB sera en mesure d'utiliser l'indice beaucoup plus efficacement - pour que je puisse le faire si j'ai un insertion de 100 enregistrements, je peux vous en protéger et exécuter 100 requêtes de sélection différentes et 100 requêtes d'insertion / mise à jour différentes, ou Utilisez in () d'une manière ou d'une autre? Cela me semble que c'est plus sûr sur le dB (j'utilise sur la touche DUP pendant un certain temps dans de très grands dbs, c'est très efficace).


@galz pouvez-vous s'il vous plaît liens Quelles caractéristiques sur la touche DUP se réfère?


@ Leventepánczél - dev.mysql.com/doc/refman /8.0/fr/insert-on-duplicate.html



-2
votes

Vous pouvez utiliser SaveOnUpDate () de la classe de session.


1 commentaires

SaveOnUpdate () Est-ce que pas résout ce problème, spécialement dans le cas d'utilisation décrit par galz. SaveOuPDate essaiera de mettre à jour si l'identifiant est défini (et ce n'est pas attribué ) et essaiera insérer s'il s'agit d'une nouvelle instance d'objet (non matière si un enregistrement avec le même identifiant existe dans la base de données).



3
votes

hibernate peut lancer un contrainteViolationException lorsque vous essayez d'insérer une ligne qui enfreint une contrainte (y compris une contrainte unique). Si vous n'obtenez pas cette exception, vous pouvez obtenir une autre exception générale hibernate - cela dépend de la version de Hibernate et de la capacité d'hibernation à cartographier l'exception MySQL à une exception hibernate dans la version et le type de base de données que vous utilisez ( Je n'ai pas testé tout sur tout).

Vous n'obtiendrez que l'exception après avoir appelé flush () , vous devez donc vous assurer que cela se trouve également dans votre bloc d'essai.

Je ferais veiller à la mise en œuvre de solutions dans lesquelles vous vérifiez que la ligne existe d'abord. Si plusieurs sessions mettent à jour le tableau simultanément, vous pouvez obtenir une condition de course. Deux processus lisent la rangée à la fois au même moment pour voir s'il existe; Ils détectent tous les deux que ce n'est pas là, puis ils essaient tous les deux de créer une nouvelle ligne. On va échouer selon qui gagne la course.

Une meilleure solution consiste à tenter l'insert d'abord et s'il échoue, suppose qu'il y avait déjà là. Cependant, une fois que vous avez une exception, vous devrez revenir en arrière, de sorte que vous limiterez la manière dont vous pouvez utiliser cette approche.


0 commentaires