J'obtiens une erreur de mise en veille prolongée. Je suis en mesure d'identifier la fonction à l'origine du problème. Malheureusement, il existe plusieurs appels de base de données dans la fonction. Je ne parviens pas à trouver la ligne qui cause le problème car la mise en veille prolongée vide la session à la fin de la transaction. L'erreur de mise en veille prolongée mentionnée ci-dessous ressemble à une erreur générale. Il ne mentionne même pas quel Bean est à l'origine du problème. Quelqu'un familier avec cette erreur de mise en veille prolongée?
org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1
at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:93)
at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:79)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransacti
onManager.java:500)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManag
er.java:473)
at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(Transaction
AspectSupport.java:267)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
Réponses:
Sans code et mappages pour vos transactions, il sera pratiquement impossible d'étudier le problème.
Cependant, pour mieux comprendre ce qui cause le problème, essayez ce qui suit:
J'espère que cela pourra aider.
la source
J'ai eu la même exception lors de la suppression d'un enregistrement par ID qui n'existe pas du tout. Vérifiez donc que l'enregistrement que vous mettez à jour / supprimez existe réellement dans la base de données
la source
Solution: dans le fichier de mappage Hibernate pour la propriété id, si vous utilisez une classe de générateur, pour cette propriété, vous ne devez pas définir la valeur explicitement à l'aide d'une méthode setter.
Si vous définissez la valeur de la propriété Id explicitement, cela entraînera l'erreur ci-dessus. Vérifiez ceci pour éviter cette erreur. ou C'est une erreur lorsque vous mentionnez dans le fichier de mappage le générateur de champs = "native" ou "incremental" et dans votre BASE DE DONNÉES la table mappée n'est pas auto_incremented Solution: Accédez à votre DATABASE et mettez à jour votre table pour définir auto_increment
la source
Cela m'est arrivé une fois par accident lorsque j'attribuais des identifiants spécifiques à certains objets (tests) et que j'essayais de les enregistrer dans la base de données. Le problème était que dans la base de données il y avait une politique spécifique pour la configuration des ID des objets. N'attribuez simplement pas d'identifiant si vous avez une politique au niveau d'Hibernate.
la source
Dans mon cas, je suis arrivé à cette exception dans deux cas similaires:
@Transactional
j'ai eu un appel à un autre service (avec de longs délais de réponse). La méthode met à jour certaines propriétés de l'entité (après la méthode, l'entité existe toujours dans la base de données). Si l'utilisateur demande deux fois la méthode (car il pense que cela ne fonctionne pas la première fois) en quittant la méthode transactionnelle la deuxième fois, Hibernate tente de mettre à jour une entité qui a déjà changé son état depuis le début de la transaction. Lorsque Hibernate recherche une entité dans un état et trouve la même entité mais déjà modifiée par la première requête, il lève une exception car il ne peut pas mettre à jour l'entité. C'est comme un conflit dans GIT.Conclusion: dans mon cas, ce n'était pas un problème que l'on retrouve dans le code. Cette exception est levée lorsque Hibernate constate que l'entité extraite pour la première fois de la base de données a changé pendant la transaction en cours , il ne peut donc pas la vider dans la base de données car Hibernate ne sait pas quelle est la version correcte de l'entité: celle qui est en cours extraction de transaction au début; ou celui déjà stocké dans la base de données.
Solution: pour résoudre le problème, vous devrez jouer avec le LockMode Hibernate pour trouver celui qui correspond le mieux à vos besoins.
la source
LockMode.READ
ouLockMode.OPTIMISTIC
.Je viens de rencontrer ce problème et j'ai découvert que je supprimais un enregistrement et que j'essayais de le mettre à jour par la suite dans une transaction Hibernate.
la source
Cela peut se produire lorsque des déclencheurs exécutent des requêtes DML (modification de données) supplémentaires qui affectent le nombre de lignes. Ma solution était d'ajouter ce qui suit en haut de mon déclencheur:
la source
J'étais confronté au même problème. Le code fonctionnait dans l'environnement de test. Mais cela ne fonctionnait pas dans l'environnement de mise en scène.
Le problème était que la table avait une seule entrée pour chaque clé primaire lors du test de la table DB. Mais dans la base de données intermédiaire, il y avait plusieurs entrées pour la même clé primaire. (Le problème est dans la base de données intermédiaire, la table n'avait aucune contrainte de clé primaire et il y avait plusieurs entrées.)
Ainsi, chaque fois que l'opération de mise à jour échoue. Il essaie de mettre à jour un enregistrement unique et s'attend à obtenir un nombre de mises à jour égal à 1. Mais comme il y avait 3 enregistrements dans la table pour la même clé primaire, le nombre de mises à jour des résultats trouve 3. Puisque le nombre de mises à jour prévu et le nombre de mises à jour des résultats réels ne correspondent pas , Il lève une exception et revient en arrière.
Après le, j'ai supprimé tous les enregistrements qui ont une clé primaire en double et ajouté des contraintes de clé primaire. Cela fonctionne bien.
nombre de lignes réel: 0 // signifie qu'aucun enregistrement n'a été trouvé pour mettre à jour
update: 0 // signifie qu'aucun enregistrement n'a été trouvé, donc aucune mise à jour n'est
attendue: 1 // signifie au moins 1 enregistrement attendu avec la clé dans la table de base de données.
Ici, le problème est que la requête essaie de mettre à jour un enregistrement pour une clé, mais hibernate n'a trouvé aucun enregistrement avec la clé.
la source
Comme Julius le dit, cela se produit lorsqu'une mise à jour se produit sur un objet dont les enfants sont supprimés. (Probablement parce qu'il y avait un besoin d'une mise à jour pour tout l'objet Père et parfois nous préférons supprimer les enfants et les réinsérer sur le Père (nouveau, ancien n'a pas d'importance) avec toutes les autres mises à jour que le père pourrait avoir sur l'un des ses autres champs simples) Donc ... pour que cela fonctionne, supprimez les enfants (dans une transaction) en appelant
childrenList.clear()
(Ne parcourez pas les enfants et supprimez chacun d'eux avec certainschildDAO.delete(childrenList.get(i).delete()))
et définissez@OneToMany(cascade = CascadeType.XXX ,orphanRemoval=true)
du côté de l'objet père. Mettez ensuite à jour le père (FatherDAO.update (père)). (Répétez pour chaque objet père) Le résultat est que les enfants ont leur lien avec leur père enlevé et ensuite ils sont enlevés comme orphelins par le cadre.la source
J'ai rencontré ce problème où nous avions une relation un-plusieurs.
Dans le fichier de mappage hbm hibernate pour master, pour un objet avec un arrangement de type défini, ajouté
cascade="save-update"
et cela a bien fonctionné.Sans cela, par défaut, Hibernate essaie de mettre à jour un enregistrement inexistant et, ce faisant, l'insère à la place.
la source
Cela peut également arriver lorsque vous essayez
UPDATE
une CLÉ PRIMAIRE .la source
J'ai eu le même problème et j'ai vérifié que cela pouvait se produire en raison de la clé primaire d'incrémentation automatique. Pour résoudre ce problème, n'insérez pas de valeur d'incrémentation automatique avec l'ensemble de données. Insérez des données sans la clé primaire.
la source
Une autre façon d'obtenir cette erreur est si vous avez un élément nul dans une collection.
la source
cela se produit lorsque vous essayez de supprimer le même objet, puis de mettre à jour à nouveau le même objet, utilisez-le après la suppression
session.clear ();
la source
Cela m'est arrivé aussi, car j'avais mon identifiant Long, et je recevais de la vue la valeur 0, et lorsque j'ai essayé d'enregistrer dans la base de données, j'ai eu cette erreur, puis je l'ai corrigée en définissant l'identifiant sur null.
la source
J'ai rencontré ce problème lorsque je commençais et validais manuellement des transactions dans la méthode annotée comme
@Transactional
. J'ai résolu le problème en détectant si une transaction active existait déjà.Ensuite, j'ai autorisé Spring à gérer la validation de la transaction.
la source
Cela se produit lorsque vous avez déclaré le Bean géré JSF comme
quand vous devez déclarer comme
Cordialement;
la source
J'ai eu cette erreur lorsque j'ai essayé de mettre à jour un objet avec un identifiant qui n'existait pas dans la base de données. La raison de mon erreur était que j'avais attribué manuellement une propriété avec le nom `` id '' à la représentation JSON côté client de l'objet, puis lors de la désérialisation de l'objet côté serveur, cette propriété `` id '' écraserait la variable d'instance ( également appelé 'id') qu'Hibernate était censé générer. Faites donc attention aux collisions de noms si vous utilisez Hibernate pour générer des identifiants.
la source
J'ai également rencontré le même défi. Dans mon cas, je mettais à jour un objet qui n'existait même pas, en utilisant
hibernateTemplate
.En fait, dans mon application, je recevais un objet DB à mettre à jour. Et tout en mettant à jour ses valeurs, j'ai également mis à jour son identifiant par erreur, je suis allé le mettre à jour et suis tombé sur ladite erreur.
J'utilise
hibernateTemplate
pour les opérations CRUD.la source
Après avoir lu toutes les réponses, je n'ai trouvé personne pour parler de l'attribut inverse de l'hibernation.
À mon avis, vous devriez également vérifier dans votre cartographie des relations si le mot clé inverse est convenablement réglé. Le mot clé inversé est créé pour définir de quel côté est le propriétaire pour maintenir la relation. La procédure de mise à jour et d'insertion varie en fonction de cet attribut.
Supposons que nous ayons deux tables:
principal_table , middle_table
avec une relation de un à plusieurs . Les classes de mappage hiberntate sont respectivement Principal et Middle .
Ainsi, la classe Principal a un SET d' objets Middle . Le fichier de mappage xml doit être comme suit:
Comme l'inverse est défini sur "true", cela signifie que la classe "Middle" est le propriétaire de la relation, donc la classe Principal NE METTE PAS À JOUR la relation.
Ainsi, la procédure de mise à jour pourrait être implémentée comme ceci:
Cela a fonctionné pour moi, mais vous pouvez suggérer quelques éditions afin d'améliorer la solution. De cette façon, nous apprendrons tous.
la source
Dans notre cas, nous avons finalement découvert la cause première de StaleStateException.
En fait, nous supprimions la ligne deux fois en une seule session de mise en veille prolongée. Auparavant, nous utilisions ojdbc6 lib, et c'était correct dans cette version.
Mais lorsque nous avons mis à niveau vers odjc7 ou ojdbc8, la suppression des enregistrements deux fois soulevait une exception. Il y avait un bogue dans notre code où nous supprimions deux fois, mais ce n'était pas évident dans ojdbc6.
Nous avons pu reproduire avec ce morceau de code:
Au premier vidage, la mise en veille prolongée va et fait des changements dans la base de données. Pendant le 2e vidage, la mise en veille prolongée compare l'objet de la session avec l'enregistrement de la table réelle, mais n'a pas pu en trouver un, d'où l'exception.
la source
Ce problème se produit principalement lorsque nous essayons de sauvegarder ou de mettre à jour l'objet qui est déjà récupéré en mémoire par une session en cours. Si vous avez récupéré un objet de la session et que vous essayez de mettre à jour dans la base de données, cette exception peut être levée.
J'ai utilisé session.evict (); pour supprimer d'abord le cache stocké en veille prolongée ou si vous ne voulez pas prendre le risque de perdre des données, mieux vaut créer un autre objet pour stocker la température des données.
la source
Problème Hibernate 5.4.1 et HHH-12878
Avant Hibernate 5.4.1, les exceptions d'échec de verrouillage optimiste (par exemple,
StaleStateException
ouOptimisticLockException
) n'incluaient pas l'instruction failing.Le problème HHH-12878 a été créé pour améliorer Hibernate afin que lors du lancement d'une exception de verrouillage optimiste, l'
PreparedStatement
implémentation JDBC soit également enregistrée:Temps de test
Tout d'abord, nous allons définir une
Post
entité qui définit une@Version
propriété, permettant ainsi le mécanisme de verrouillage optimiste implicite :Nous activerons le traitement par lots JDBC en utilisant les 3 propriétés de configuration suivantes:
Nous allons créer 3
Post
entités:Et Hibernate exécutera une insertion par lots JDBC:
Nous savons donc que le traitement par lots JDBC fonctionne très bien.
Maintenant, répliquons le problème de verrouillage optimiste:
La première transaction sélectionne toutes les
Post
entités et modifie letitle
propriétés.Cependant, avant que le premier ne
EntityManager
soit vidé, nous allons exécuter une deuxième transition en utilisant laexecuteSync
méthode.La deuxième transaction modifie la première
Post
, elleversion
va donc être incrémentée:Maintenant, lorsque la première transaction essaie de vider le
EntityManager
, nous obtiendrons leOptimisticLockException
:Vous devez donc mettre à niveau vers Hibernate 5.4.1 ou une version plus récente pour bénéficier de cette amélioration.
la source
Cela se produit si vous modifiez quelque chose dans l'ensemble de données à l'aide d'une requête SQL native mais que l'objet persistant pour le même ensemble de données est présent dans le cache de session. Utilisez session.evict (yourObject);
la source
Hibernate met en cache les objets de la session. Si l'objet est accédé et modifié par plus d'un utilisateur, il
org.hibernate.StaleStateException
peut alors être jeté. Il peut être résolu avec la méthode d'entité de fusion / rafraîchissement avant d'enregistrer ou d'utiliser le verrouillage. Plus d'infos: http://java-fp.blogspot.lt/2011/09/orghibernatestalestateexception-batch.htmlla source
Un des cas
la source
Je faisais face à cette exception et la mise en veille prolongée fonctionnait bien. J'ai essayé d'insérer manuellement un enregistrement à l'aide de pgAdmin, ici le problème est devenu clair. La requête d'insertion SQL renvoie 0 insertion. et il existe une fonction de déclenchement qui cause ce problème car elle renvoie null. donc je n'ai qu'à le configurer pour qu'il revienne nouveau. et finalement j'ai résolu le problème.
espérons que cela aide n'importe quel corps.
la source
J'ai eu cette erreur car j'ai mappé par erreur la
ID
colonne en utilisantId(x => x.Id, "id").GeneratedBy.**Assigned**();
Problème résolu en utilisant
Id(x => x.Id, "id").GeneratedBy.**Identity**();
la source
Cela m'arrive parce que je n'ai pas de déclaration d'identification dans la classe de bean.
la source
Dans mon cas, il y avait un problème avec la base de données car l'un des processus stockés consommait tout le processeur, ce qui entraînait des temps de réponse de base de données élevés. Une fois que cela a été tué, le problème a été résolu.
la source