Ich erhalte folgenden Fehler im Ruhezustand. Ich kann die Funktion identifizieren, die das Problem verursacht. Leider gibt es mehrere DB-Aufrufe in der Funktion. Ich kann die Zeile, die das Problem verursacht, nicht finden, da die Sitzung am Ende der Transaktion im Ruhezustand beendet wurde. Der unten erwähnte Fehler im Ruhezustand scheint ein allgemeiner Fehler zu sein. Es wird nicht einmal erwähnt, welche Bean das Problem verursacht. Kennt jemand diesen Fehler im Ruhezustand?
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)
Antworten:
Ohne Code und Zuordnungen für Ihre Transaktionen ist es nahezu unmöglich, das Problem zu untersuchen.
Versuchen Sie jedoch Folgendes, um einen besseren Überblick über die Ursachen des Problems zu erhalten:
Hoffentlich hilft das.
quelle
Ich habe die gleiche Ausnahme beim Löschen eines Datensatzes nach ID erhalten, der überhaupt nicht vorhanden ist. Überprüfen Sie also, ob der Datensatz, den Sie aktualisieren / löschen, tatsächlich in der Datenbank vorhanden ist
quelle
Lösung: Wenn Sie in der Zuordnungsdatei für den Ruhezustand für die Eigenschaft id eine Generatorklasse verwenden, sollten Sie für diese Eigenschaft den Wert nicht explizit mithilfe einer Setter-Methode festlegen.
Wenn Sie den Wert der Id-Eigenschaft explizit festlegen, wird der obige Fehler angezeigt. Überprüfen Sie dies, um diesen Fehler zu vermeiden. oder Es wird ein Fehler angezeigt, wenn Sie in der Zuordnungsdatei den Feldgenerator = "native" oder "inkrementell" erwähnen und in Ihrer DATABASE die zugeordnete Tabelle nicht auto_incremented ist. Lösung: Gehen Sie zu Ihrer DATABASE und aktualisieren Sie Ihre Tabelle, um auto_increment festzulegen
quelle
Dies ist mir einmal zufällig passiert, als ich einigen Objekten bestimmte IDs zugewiesen habe (Testen) und dann versucht habe, sie in der Datenbank zu speichern. Das Problem war, dass es in der Datenbank eine spezielle Richtlinie zum Einrichten der IDs der Objekte gab. Weisen Sie nur keine ID zu, wenn Sie eine Richtlinie im Ruhezustand haben.
quelle
In meinem Fall bin ich in zwei ähnlichen Fällen zu dieser Ausnahme gekommen:
@Transactional
ich einen Anruf bei einem anderen Dienst (mit langen Antwortzeiten). Die Methode aktualisiert einige Eigenschaften der Entität (nach der Methode ist die Entität noch in der Datenbank vorhanden). Wenn der Benutzer beim zweiten Verlassen der Transaktionsmethode zweimal die Methode anfordert (da er glaubt, dass sie beim ersten Mal nicht funktioniert), versucht Hibernate, eine Entität zu aktualisieren, die ihren Status bereits zu Beginn der Transaktion geändert hat. Wenn der Ruhezustand nach einer Entität in einem Status sucht und dieselbe Entität gefunden hat, die jedoch bereits durch die erste Anforderung geändert wurde, wird eine Ausnahme ausgelöst, da die Entität nicht aktualisiert werden kann. Es ist wie ein Konflikt in der GIT.Fazit: In meinem Fall war es kein Problem, das im Code zu finden ist. Diese Ausnahme wird ausgelöst, wenn Hibernate feststellt, dass sich die zum ersten Mal aus der Datenbank abgerufene Entität während der aktuellen Transaktion geändert hat , sodass sie nicht in die Datenbank gelöscht werden kann, da Hibernate nicht weiß, welche Version der Entität korrekt ist: die aktuelle Transaktionsabruf am Anfang; oder die bereits in der Datenbank gespeicherte.
Lösung: Um das Problem zu lösen, müssen Sie mit dem Hibernate LockMode spielen , um den für Ihre Anforderungen am besten geeigneten zu finden.
quelle
LockMode.READ
oderLockMode.OPTIMISTIC
.Ich bin gerade auf dieses Problem gestoßen und habe festgestellt, dass ich einen Datensatz lösche und danach versuche, ihn in einer Hibernate-Transaktion zu aktualisieren.
quelle
Dies kann passieren, wenn Trigger zusätzliche DML-Abfragen (Datenmodifikation) ausführen, die sich auf die Zeilenanzahl auswirken. Meine Lösung bestand darin, oben am Auslöser Folgendes hinzuzufügen:
quelle
Ich stand vor dem gleichen Problem. Der Code funktionierte in der Testumgebung. Aber es funktionierte nicht in einer Staging-Umgebung.
Das Problem war, dass die Tabelle einen einzelnen Eintrag für jeden Primärschlüssel beim Testen der DB-Tabelle hatte. In der Staging-Datenbank gab es jedoch mehrere Einträge für denselben Primärschlüssel. (Das Problem ist, dass in der Staging-Datenbank für die Tabelle keine Primärschlüsseleinschränkungen vorhanden waren und auch mehrere Einträge vorhanden waren.)
Jedes Mal, wenn ein Update durchgeführt wird, schlägt dies fehl. Es wird versucht, einen einzelnen Datensatz zu aktualisieren, und es wird erwartet, dass die Aktualisierungsanzahl 1 beträgt. Da jedoch 3 Datensätze in der Tabelle für denselben Primärschlüssel vorhanden sind, wird die Anzahl der Ergebnisaktualisierungen auf 3 festgelegt. Da die erwartete Aktualisierungsanzahl und die tatsächliche Ergebnisaktualisierungsanzahl nicht übereinstimmen Es löst eine Ausnahme aus und rollt zurück.
Nach dem habe ich alle Datensätze entfernt, die einen doppelten Primärschlüssel haben, und Primärschlüsseleinschränkungen hinzugefügt. Es funktioniert gut.
tatsächliche Zeilenanzahl: 0 // bedeutet, dass kein Datensatz zum Aktualisieren der
Aktualisierung gefunden wurde: 0 // bedeutet, dass kein Datensatz gefunden wurde, sodass keine Aktualisierung
erwartet wird: 1 // bedeutet, dass mindestens 1 Datensatz mit Schlüssel in der DB-Tabelle erwartet wird.
Hier besteht das Problem darin, dass die Abfrage versucht, einen Datensatz für einen Schlüssel zu aktualisieren, der Ruhezustand jedoch keinen Datensatz mit dem Schlüssel gefunden hat.
quelle
Wie Julius sagt, geschieht dies, wenn ein Update für ein Objekt erfolgt, dessen untergeordnete Elemente gelöscht werden. (Wahrscheinlich, weil ein Update für das gesamte Vaterobjekt erforderlich war und wir es manchmal vorziehen, die Kinder zu löschen und sie erneut in den Vater einzufügen (neu, alt spielt keine Rolle), zusammen mit anderen Updates, die der Vater für eines der Objekte haben könnte seine anderen einfachen Felder) Also ... damit dies funktioniert, löschen Sie die Kinder (innerhalb einer Transaktion) durch Aufrufen
childrenList.clear()
(Schleifen Sie nicht durch die Kinder und löschen Sie jedes mit einigenchildDAO.delete(childrenList.get(i).delete()))
und Einstellungen@OneToMany(cascade = CascadeType.XXX ,orphanRemoval=true)
auf der Seite des Vaterobjekts. Aktualisieren Sie dann den Vater (dadDAO.update (Vater)). (Wiederholen Sie dies für jedes Vaterobjekt.) Das Ergebnis ist, dass Kindern die Verbindung zu ihrem Vater entzogen wird und sie dann vom Framework als Waisenkinder entfernt werden.quelle
Ich bin auf dieses Problem gestoßen, bei dem wir eine Eins-Viele-Beziehung hatten.
In der Ruhezustand-Hbm-Zuordnungsdatei für Master, für Objekt mit festgelegter Typanordnung, hinzugefügt
cascade="save-update"
und es hat gut funktioniert.Ohne dies versucht der Ruhezustand standardmäßig, ein Update für einen nicht vorhandenen Datensatz durchzuführen, und fügt stattdessen ein.
quelle
Dies kann auch passieren, wenn Sie versuchen,
UPDATE
einen PRIMARY KEY zu verwenden .quelle
Ich habe das gleiche Problem und ich habe überprüft, dass dies aufgrund des Auto-Inkrement-Primärschlüssels auftreten kann. Um dieses Problem zu lösen, fügen Sie keinen automatischen Inkrementwert in den Datensatz ein. Daten ohne Primärschlüssel einfügen.
quelle
Eine andere Möglichkeit, diesen Fehler zu erhalten, besteht darin, ein Nullelement in einer Sammlung zu haben.
quelle
Dies passiert, wenn Sie versuchen, dasselbe Objekt zu löschen und dann dasselbe Objekt erneut zu aktualisieren. Verwenden Sie dies nach dem Löschen
session.clear ();
quelle
Dies ist mir auch passiert, weil ich meine ID als Long hatte und aus der Sicht den Wert 0 erhielt. Als ich versuchte, in der Datenbank zu speichern, bekam ich diesen Fehler, dann habe ich ihn behoben, indem ich die ID auf null gesetzt habe.
quelle
Ich bin auf dieses Problem gestoßen, als ich Transaktionen innerhalb der als "annotierten Methode" manuell gestartet und festgeschrieben habe
@Transactional
. Ich habe das Problem behoben, indem festgestellt wurde, ob bereits eine aktive Transaktion vorhanden war.Dann erlaubte ich Spring, die Transaktion festzuschreiben.
quelle
Dies geschieht, wenn Sie die JSF Managed Bean als deklariert haben
wann sollten Sie als deklarieren
Grüße;
quelle
Ich habe diesen Fehler erhalten, als ich versucht habe, ein Objekt mit einer ID zu aktualisieren, die in der Datenbank nicht vorhanden war. Der Grund für meinen Fehler war, dass ich der clientseitigen JSON-Darstellung des Objekts manuell eine Eigenschaft mit dem Namen 'id' zugewiesen hatte. Beim Deserialisieren des Objekts auf der Serverseite überschrieb diese 'id'-Eigenschaft dann die Instanzvariable ( auch 'id' genannt), die Hibernate generieren sollte. Achten Sie daher darauf, Kollisionen zu benennen, wenn Sie den Ruhezustand zum Generieren von Bezeichnern verwenden.
quelle
Ich bin auch auf die gleiche Herausforderung gestoßen. In meinem Fall habe ich ein Objekt, das noch nicht einmal vorhanden war, mit aktualisiert
hibernateTemplate
.Tatsächlich habe ich in meiner Anwendung ein DB-Objekt zum Aktualisieren erhalten. Und während ich seine Werte aktualisierte, aktualisierte ich versehentlich auch seine ID und fuhr fort, sie zu aktualisieren und stieß auf diesen Fehler.
Ich benutze
hibernateTemplate
für CRUD-Operationen.quelle
Nachdem ich alle Antworten gelesen hatte, fand ich niemanden, der über das inverse Attribut des Ruhezustands sprach.
Meiner Meinung nach sollten Sie in Ihrer Beziehungszuordnung auch überprüfen, ob das inverse Schlüsselwort richtig eingestellt ist. Invers Schlüsselwort wird erstellt, um zu definieren, auf welcher Seite der Eigentümer die Beziehung aufrechterhält. Das Verfahren zum Aktualisieren und Einfügen variiert je nach Attribut.
Nehmen wir an, wir haben zwei Tabellen:
Principal_Table , Middle_Table
mit einer Beziehung von eins zu vielen . Die Hiberntate-Mapping-Klassen sind Principal und Middle .
Die Principal- Klasse verfügt also über einen SET von Middle- Objekten. Die XML-Zuordnungsdatei sollte wie folgt aussehen:
Da die Umkehrung auf "wahr" gesetzt ist, bedeutet dies, dass "Mittelklasse" der Beziehungseigentümer ist, also wird die Hauptklasse dies tun NICHT AKTUALISIERT die Beziehung .
Das Verfahren zum Aktualisieren könnte also folgendermaßen implementiert werden:
Dies hat bei mir funktioniert, aber Sie können einige Editionen vorschlagen, um die Lösung zu verbessern. Auf diese Weise werden wir alle lernen.
quelle
In unserem Fall haben wir endlich die Grundursache für StaleStateException herausgefunden.
Tatsächlich haben wir die Zeile zweimal in einer einzigen Sitzung im Ruhezustand gelöscht. Früher haben wir ojdbc6 lib verwendet, und das war in dieser Version in Ordnung.
Beim Upgrade auf odjc7 oder ojdbc8 löste das zweimalige Löschen von Datensätzen jedoch eine Ausnahme aus. Es gab einen Fehler in unserem Code, bei dem wir zweimal löschten, aber das war in ojdbc6 nicht ersichtlich.
Wir konnten mit diesem Code reproduzieren:
Beim ersten Flush geht der Ruhezustand und nimmt Änderungen in der Datenbank vor. Während des zweiten Ruhezustands vergleicht der Ruhezustand das Sitzungsobjekt mit dem Datensatz der tatsächlichen Tabelle, konnte jedoch keinen finden, daher die Ausnahme.
quelle
Dieses Problem tritt hauptsächlich auf, wenn wir versuchen, das Objekt zu speichern oder zu aktualisieren, das bereits von einer laufenden Sitzung in den Speicher abgerufen wurde. Wenn Sie ein Objekt aus der Sitzung abgerufen haben und versuchen, es in der Datenbank zu aktualisieren, wird diese Ausnahme möglicherweise ausgelöst.
Ich habe session.evict () verwendet. Um den im Ruhezustand gespeicherten Cache zuerst zu entfernen oder wenn Sie nicht das Risiko eingehen möchten, Daten zu verlieren, sollten Sie ein anderes Objekt zum Speichern der Datentemperatur erstellen.
quelle
Problem mit Hibernate 5.4.1 und HHH-12878
Vor Hibernate 5.4.1 enthielten die optimistischen Ausnahmen für Sperrfehler (z. B.
StaleStateException
oderOptimisticLockException
) nicht die Fehleranweisung.Das Problem HHH-12878 wurde erstellt, um den Ruhezustand zu verbessern, sodass beim Auslösen einer optimistischen Sperrausnahme auch die JDBC-
PreparedStatement
Implementierung protokolliert wird:Testzeit
Zunächst definieren wir eine
Post
Entität, die eine@Version
Eigenschaft definiert , wodurch der implizite optimistische Sperrmechanismus aktiviert wird :Wir werden die JDBC-Stapelverarbeitung mit den folgenden 3 Konfigurationseigenschaften aktivieren:
Wir werden 3
Post
Entitäten erstellen :Und Hibernate führt eine JDBC-Batch-Einfügung aus:
Wir wissen also, dass JDBC-Batching einwandfrei funktioniert.
Lassen Sie uns nun das optimistische Problem beim Sperren wiederholen:
Die erste Transaktion wählt alle
Post
Entitäten aus und ändert dietitle
Eigenschaften.Bevor der erste
EntityManager
gelöscht wird, führen wir jedoch einen zweiten Übergang mit derexecuteSync
Methode aus.Die zweite Transaktion ändert die erste
Post
, sodassversion
sie erhöht wird:Wenn nun die erste Transaktion versucht, das zu leeren
EntityManager
, erhalten wir FolgendesOptimisticLockException
:Sie müssen also auf Hibernate 5.4.1 oder höher aktualisieren, um von dieser Verbesserung zu profitieren.
quelle
Dies ist passiert, wenn Sie etwas im Datensatz mithilfe einer nativen SQL-Abfrage ändern, das persistente Objekt für denselben Datensatz jedoch im Sitzungscache vorhanden ist. Verwenden Sie session.evict (yourObject).
quelle
Im Ruhezustand werden Objekte aus der Sitzung zwischengespeichert. Wenn mehr als ein Benutzer auf das Objekt zugreift und es ändert,
org.hibernate.StaleStateException
kann es ausgelöst werden. Es kann mit der Entitätsmethode zum Zusammenführen / Aktualisieren gelöst werden, bevor die Sperre gespeichert oder verwendet wird. Weitere Informationen: http://java-fp.blogspot.lt/2011/09/orghibernatestalestateexception-batch.htmlquelle
Einer der Fälle
quelle
Ich war mit dieser Ausnahme konfrontiert und der Winterschlaf funktionierte gut. Ich habe versucht, einen Datensatz mit pgAdmin manuell einzufügen. Hier wurde das Problem klar. SQL Insert Query gibt 0 Insert zurück. und es gibt eine Triggerfunktion, die dieses Problem verursacht, weil sie null zurückgibt. also muss ich es nur einstellen, um neu zurückzugeben. und schließlich habe ich das Problem gelöst.
hoffe das hilft jedem körper.
quelle
Ich habe diesen Fehler erhalten, weil ich die
ID
Spalte fälschlicherweise mit zugeordnet habeId(x => x.Id, "id").GeneratedBy.**Assigned**();
Problem behoben mit
Id(x => x.Id, "id").GeneratedBy.**Identity**();
quelle
Dies passiert mir, weil mir die ID-Deklaration in der Bean-Klasse fehlt.
quelle
In meinem Fall gab es ein Problem mit der Datenbank, da einer der gespeicherten Prozesse die gesamte CPU verbrauchte und hohe DB-Antwortzeiten verursachte. Sobald dies getötet wurde, wurde das Problem behoben.
quelle