webentwicklung-frage-antwort-db.com.de

Fehler beim Löschen des Ruhezustands: Die Stapelaktualisierung hat unerwartete Zeilenanzahl zurückgegeben

Ich habe diese Methode unten geschrieben, die einen Mitgliedsdatensatz aus der Datenbank löschen soll. Wenn ich es jedoch in meinem Servlet verwende, wird ein Fehler ausgegeben.

MemberDao-Klasse

public static void deleteMember(Member member) {
    Session hibernateSession = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction tx = hibernateSession.beginTransaction();
    hibernateSession.delete(member);
    tx.commit();
}

Controller Teil

if(delete != null) {
    HttpSession httpSession = request.getSession();
    Member member = (Member) httpSession.getAttribute("member");

    MemberDao.deleteMember(member);

    nextPage = "ledenlijst.jsp";
}

HTTP-Status 500

org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

Manchmal gibt es sogar diesen Fehler, wenn ich versuche, die Seite mehrmals auszuführen.

org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update

Weiß jemand, was genau diese Fehler verursacht?

20
Kid Diamond

Der Fehler kann verschiedene Ursachen haben. Ich nehme den Kredit dafür nicht an, fand ihn hier .

  1. Das Löschen der Daten vor dem Festschreiben des Objekts kann dazu führen, dass alle Daten gelöscht werden Objekt ist noch verfügbar.
  2. Wenn das Objekt einen Primärschlüssel hat, der automatisch generiert wird, und Sie sind einen zugewiesenen Schlüssel erzwingen
  3. wenn Sie das Objekt reinigen, bevor Sie das Objekt an .__ übergeben. Datenbank.
  4. Null oder falsche ID: Wenn Sie die ID auf Null oder etwas anderes setzen, wird Der Ruhezustand versucht zu aktualisieren, anstatt einzufügen.
  5. Object is Stale: Hibernate speichert Objekte aus der Sitzung. Wenn der Objekt wurde geändert, und Hibernate weiß nichts davon, es wird Diese Ausnahme auslösen - beachten Sie die StaleStateException

Schauen Sie sich auch die diese Antwort by beny23 an, die einige weitere Hinweise gibt, um das Problem zu finden.

  • Setzen Sie in Ihrer Hibernate-Konfiguration hibernate.show_sql auf true. Dies sollte Ihnen zeigen, welche SQL ausgeführt wird und das Problem verursacht.
  • Legen Sie die Protokollierungsstufen für Spring und Hibernate auf DEBUG fest. Dies gibt Ihnen eine bessere Vorstellung davon, welche Zeile das Problem verursacht.
  • Erstellen Sie einen Komponententest, der das Problem repliziert, ohne einen Transaktionsmanager in Spring zu konfigurieren. Auf diese Weise erhalten Sie eine bessere Vorstellung von der fehlerhaften Codezeile.
42
Ashish Jagtap

Die Ausnahme org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 Wird ausgelöst, wenn Hibernate feststellt, dass die Entität, die er in die Datenbank leeren möchte, nicht genau so ist wie zu Beginn der Transaktion.

Ich habe zwei verschiedene Anwendungsfälle näher beschrieben, die mir hier passieren.

1
Sergio Lema

In meinem Fall wurde diese Ausnahme durch falsche Entitätszuordnung verursacht. Es gab keine Kaskade für Relation, und die referenzierte untergeordnete Entität wurde nicht gespeichert, bevor sie von einem übergeordneten Element versucht wurde, darauf zu verweisen. Ändern Sie es in 

    @OneToMany(cascade = CascadeType.ALL)

das Problem behoben.

Der beste Weg, die Ursache für diese Ausnahmebedingung zu finden, ist sicherlich die Einstellung von show_sql und DEBUG für Protokolle. Sie wird nur bei der SQL-Instanz stehen, die das Problem verursacht hat.

1
mdziob

Das gleiche Problem trat bei Hibernate/JPA 2.1 auf, wenn memcached als sekundärer Cache verwendet wurde. Sie würden die oben genannte Ausnahme zusammen mit einer StaleStateException erhalten. Die Entschließung war anders als zuvor erwähnt. 

Ich habe festgestellt, dass der Ruhezustand bei einer Operation, die Löschungen verschachtelt und aus derselben Tabelle und Transaktion auswählt (sucht), überlastet werden kann und diese veraltete Statusausnahme melden kann. Es würde für uns nur während der Produktion vorkommen, da mehrere identische Operationen für verschiedene Entitäten in derselben Tabelle auftreten würden. Sie sehen die Systemzeitüberschreitung und Ausnahmen. 

Die Lösung ist einfach effizienter zu sein. Versuchen Sie, anstatt in einer Schleife zu verschachteln, zu klären, welche Elemente gelesen werden müssen, und zwar vorzugsweise in einem Vorgang. Führen Sie dann das Löschen in einem separaten Vorgang aus. Wieder alle in der gleichen Transaktion, aber pflegen Sie den Ruhezustand nicht mit Lese-, Lösch-, Lese- und Löschvorgängen.

Dies ist viel schneller und reduziert die Housekeeping-Belastung für Hibernate erheblich. Das Problem ist verschwunden. Dies tritt auf, wenn Sie einen sekundären Cache verwenden und sonst nicht auftreten, da die Last zur Auflösung ohne sekundären Cache in der Datenbank liegt. Das ist ein anderes Problem.

0
sagneta

das ist die Lösung für meinen Fall, vielleicht hilft es Ihnen!

Tatsächlich handelt es sich um ein Konvertierungsproblem zwischen einem Datenbankfeldtyp (Zeitstempel in postgreSQL) und seinem entsprechenden Eigenschaftstyp (Calendar) in der Hibernat-XML-Datei ..__ Wenn Hibernate diese Aktualisierungsanforderung stellte, wurde die Zeile nicht abgerufen, da die Anfrage abfragt mit einem fehlerhaften konvertieren Kalenderwert . Also habe ich einfach den Eigenschaftentyp "Calendar" in "Date" in der Hibernate-XML-Datei ersetzt und das Problem wurde behoben.

0
Julien

Ich stand vor demselben Problem ... Der Code funktionierte in der Testumgebung. In der Inszenierungsumgebung funktionierte es jedoch nicht.

org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 3; expected: 1

Das Problem war, dass die Tabelle einen einzelnen Eintrag für jeden Primärschlüssel beim Testen der DB-Tabelle hatte. Beim Staging von DB gab es jedoch mehrere Einträge für denselben Primärschlüssel. (Problem ist beim Staging von DB, dass die Tabelle keine Primärschlüsseleinschränkungen hatte und auch mehrere Einträge vorhanden waren.)

Es wird also jedes Mal beim Aktualisierungsvorgang fehlgeschlagen. Es wird versucht, den einzelnen Datensatz zu aktualisieren, und es wird erwartet, dass die Anzahl der Aktualisierungen als 1 abgerufen wird. Da jedoch drei Datensätze in der Tabelle für denselben Primärschlüssel enthalten waren, werden in der Ergebnisaktualisierungszählung 3 gefunden Es wirft eine Ausnahme und rollt zurück.

Danach entfernte ich alle Datensätze, die über einen Primärschlüssel verfügen, und fügte Primärschlüsseleinschränkungen hinzu. Es funktioniert gut.

0
ParagFlume

ich habe dies kürzlich erlebt und was passiert ist, war, dass ich die Aktualisierungsmethode verwendet habe und es eine Ausnahme auslöste, da kein Datensatz vorhanden war. Ich habe die Methode in saveOrUpdate geändert. Es funktionierte.

0
arn-arn

Ich habe dieses Problem gehabt,

Ich habe meinen Code überprüft, es gab keine Probleme, aber als ich meine Daten überprüfte, hatte ich zwei Entitäten mit derselben ID!

Die flush() konnte also nicht funktionieren, da sie nacheinander für Batch-Updates funktioniert und 2 Zeilen gefunden hat. Daher wurde es nicht aktualisiert und warf eine Ausnahme, aber es war mein Problem. Ich weiß nicht, ob es gut für dich funktioniert oder nicht!

0