Ich habe zwei Benutzerobjekte und während ich versuche, das Objekt mit zu speichern
session.save(userObj);
Ich erhalte die folgende Fehlermeldung:
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
[com.pojo.rtrequests.User#com.pojo.rtrequests.User@d079b40b]
Ich erstelle die Sitzung mit
BaseHibernateDAO dao = new BaseHibernateDAO();
rtsession = dao.getSession(userData.getRegion(),
BaseHibernateDAO.RTREQUESTS_DATABASE_NAME);
rttrans = rtsession.beginTransaction();
rttrans.begin();
rtsession.save(userObj1);
rtsession.save(userObj2);
rtsession.flush();
rttrans.commit();
rtsession.close(); // in finally block
Ich habe auch versucht, das session.clear()
vor dem Speichern zu tun , immer noch kein Glück.
Dies ist das erste Mal, dass ich das Sitzungsobjekt erhalte, wenn eine Benutzeranforderung eingeht. Daher erhalte ich den Grund, warum dieses Objekt in der Sitzung vorhanden ist.
Irgendwelche Vorschläge?
Antworten:
Ich habe diesen Fehler schon oft gehabt und es kann ziemlich schwierig sein, ihn aufzuspüren ...
Grundsätzlich bedeutet der Ruhezustand, dass Sie zwei Objekte haben, die dieselbe Kennung (denselben Primärschlüssel) haben, aber nicht dasselbe Objekt sind.
Ich würde vorschlagen, dass Sie Ihren Code aufschlüsseln, dh Bits auskommentieren, bis der Fehler behoben ist, und dann den Code zurücksetzen, bis er zurückkommt und Sie den Fehler finden sollten.
Dies geschieht meistens über kaskadierende Speicherungen, bei denen zwischen Objekt A und B eine Kaskadenspeicherung stattfindet, Objekt B jedoch bereits mit der Sitzung verknüpft wurde, sich jedoch nicht in derselben Instanz von B befindet wie die auf A.
Welchen Primärschlüsselgenerator verwenden Sie?
Der Grund, den ich frage, ist, dass dieser Fehler damit zusammenhängt, wie Sie den Ruhezustand anweisen, den dauerhaften Zustand eines Objekts zu ermitteln (dh ob ein Objekt persistent ist oder nicht). Der Fehler kann auftreten, weil der Ruhezustand versucht, ein bereits beständiges Objekt beizubehalten. Wenn Sie den Ruhezustand speichern verwenden, wird versucht, dieses Objekt beizubehalten, und möglicherweise ist der Sitzung bereits ein Objekt mit demselben Primärschlüssel zugeordnet.
Beispiel
Angenommen, Sie haben ein Klassenobjekt im Ruhezustand für eine Tabelle mit 10 Zeilen basierend auf einer Primärschlüsselkombination (Spalte 1 und Spalte 2). Jetzt haben Sie zu einem bestimmten Zeitpunkt 5 Zeilen aus der Tabelle entfernt. Wenn Sie nun erneut versuchen, dieselben 10 Zeilen hinzuzufügen, während im Ruhezustand versucht wird, die Objekte in der Datenbank beizubehalten, werden 5 bereits entfernte Zeilen ohne Fehler hinzugefügt. Jetzt lösen die verbleibenden 5 Zeilen, die bereits vorhanden sind, diese Ausnahme aus.
Der einfache Ansatz wäre also zu überprüfen, ob Sie einen Wert in einer Tabelle aktualisiert / entfernt haben, der Teil von etwas ist, und später versuchen Sie, dieselben Objekte erneut einzufügen
quelle
Dies ist nur ein Punkt, an dem der Ruhezustand mehr Probleme verursacht als löst. In meinem Fall gibt es viele Objekte mit derselben Kennung 0, da sie neu sind und keine haben. Die Datenbank generiert sie. Irgendwo habe ich gelesen, dass 0 Signale nicht gesetzt sind. Die intuitive Möglichkeit, sie beizubehalten, besteht darin, sie zu durchlaufen und den Ruhezustand zu aktivieren, um die Objekte zu speichern. Aber das können Sie nicht tun - "Natürlich sollten Sie wissen, dass der Ruhezustand so und so funktioniert, deshalb müssen Sie ..." Jetzt kann ich versuchen, die IDs in "Lang" anstatt "Lang" zu ändern und zu prüfen, ob es dann funktioniert. Am Ende ist es einfacher, dies mit einem einfachen Mapper selbst zu tun, da der Ruhezustand nur eine zusätzliche intransparente Belastung darstellt. Ein weiteres Beispiel: Wenn Sie versuchen, Parameter aus einer Datenbank zu lesen und in einer anderen zu speichern, müssen Sie fast alle Arbeiten manuell ausführen.
quelle
USe
session.evict(object);
Mit der Funktionevict()
method wird die Instanz aus dem Sitzungscache entfernt. Speichern Sie das Objekt zum ersten Mal, indem Sie diesession.save(object)
Methode aufrufen , bevor Sie das Objekt aus dem Cache entfernen. Auf die gleiche Weise aktualisieren Sie das Objekt durch Aufrufensession.saveOrUpdate(object)
odersession.update(object)
vor dem Aufruf von evict ().quelle
Dies kann passieren, wenn Sie dasselbe Sitzungsobjekt zum Lesen und Schreiben verwendet haben. Wie? Angenommen, Sie haben eine Sitzung erstellt. Sie lesen einen Datensatz aus der Mitarbeitertabelle mit dem Primärschlüssel Emp_id = 101 Jetzt haben Sie den Datensatz in Java geändert. Und Sie werden den Mitarbeiterdatensatz in der Datenbank speichern. Wir haben hier nirgendwo eine Sitzung geschlossen. Da das gelesene Objekt auch in der Sitzung bestehen bleibt. Es widerspricht dem Objekt, das wir schreiben möchten. Daher kommt dieser Fehler.
quelle
Wie bereits oben erwähnt, bin ich auf dieses Problem gestoßen, als ich
cascade=all
an beiden Enden einerone-to-many
Beziehung war. Nehmen wir also A -> B (eins zu viele von A und viele zu eins von B) an und aktualisiere die Instanz von B in A und dann das Aufrufen von saveOrUpdate (A) führte zu einer zirkulären Speicheranforderung, dh das Speichern von A löst das Speichern von B aus, das das Speichern von A auslöst ... und in dritter Instanz, als die Entität (von A) versucht wurde dem sessionPersistenceContext hinzugefügt werden, wurde die duplicateObject-Ausnahme ausgelöst.Ich könnte es lösen, indem ich die Kaskade von einem Ende entferne.
quelle
Sie können verwenden
session.merge(obj)
, wenn Sie mit verschiedenen Sitzungen mit demselben persistenten Bezeichnerobjekt speichern.Es hat funktioniert, ich hatte vorher das gleiche Problem.
quelle
Ich bin auch auf dieses Problem gestoßen und hatte Schwierigkeiten, den Fehler zu finden.
Das Problem, das ich hatte, war das folgende:
Das Objekt wurde von einem Dao mit einer anderen Ruhezustandssitzung gelesen.
Um diese Ausnahme zu vermeiden, lesen Sie das Objekt einfach erneut mit dem Dao, das dieses Objekt später speichern / aktualisieren soll.
so:
Hoffe, dass einige Leute viel Zeit sparen!
quelle
Ich bin auf dieses Problem gestoßen durch:
Ich habe es behoben, indem ich die Ergebnisse nach dem Löschen geleert und den Cache geleert habe, bevor ich das neue Objekt gespeichert habe
quelle
Dieses Problem tritt auf, wenn wir dasselbe Sitzungsobjekt aktualisieren, mit dem wir das Objekt aus der Datenbank abgerufen haben.
Sie können die Zusammenführungsmethode für den Ruhezustand anstelle der Aktualisierungsmethode verwenden.
Beispiel: Verwenden Sie zuerst session.get () und dann session.merge (Objekt). Diese Methode verursacht keine Probleme. Wir können auch die merge () -Methode verwenden, um das Objekt in der Datenbank zu aktualisieren.
quelle
Holen Sie sich das Objekt in die Sitzung, hier ein Beispiel:
quelle
Sind Ihre ID-Zuordnungen korrekt? Wenn die Datenbank für die Erstellung der ID über eine Kennung verantwortlich ist, müssen Sie Ihr Benutzerobjekt diesem zuordnen.
quelle
Ich bin auf dieses Problem beim Löschen eines Objekts gestoßen, das weder geräumt noch eindeutig geholfen hat.
quelle
Vor der Position, an der sich wiederholende Objekte beginnen, sollten Sie die Sitzung schließen und anschließend eine neue Sitzung starten
Auf diese Weise gibt es in einer Sitzung nicht mehr als eine Entität mit derselben Kennung.
quelle
Spät zur Party, kann aber für kommende User helfen -
Ich habe dieses Problem , wenn ich wählen Sie einen Datensatz mit
getsession()
und wieder aktualisieren einen anderen Datensatz mit derselben Kennung mit derselben Sitzung das Problem verursacht. Code unten hinzugefügt.Dies sollte niemals getan werden. Die Lösung besteht entweder darin, die Sitzung vor dem Update zu entfernen oder die Geschäftslogik zu ändern.
quelle
Überprüfen Sie, ob Sie vergessen haben, die Spalte @GenerateValue für @Id einzufügen. Ich hatte das gleiche Problem mit vielen zu vielen Beziehungen zwischen Film und Genre. Das Programm hat den Ruhezustand ausgelöst: org.hibernate.NonUniqueObjectException: Dem Sitzungsfehler wurde bereits ein anderes Objekt mit demselben Bezeichnerwert zugeordnet. Ich fand später heraus, dass ich nur sicherstellen muss, dass Sie @GenerateValue für die GenreId get-Methode haben.
quelle
Überprüfen Sie einfach die ID, ob es null oder 0 wie nimmt
Hinzufügen oder Aktualisieren, wenn der Inhalt vom Formular in Pojo festgelegt wird
quelle
Ich bin neu in NHibernate und mein Problem war, dass ich mein Objekt in einer anderen Sitzung abgefragt habe als zum Speichern. Die Speichersitzung wusste also nichts über das Objekt.
Es scheint offensichtlich, aber nach dem Lesen der vorherigen Antworten habe ich überall nach 2 Objekten gesucht, nicht nach 2 Sitzungen.
quelle
@GeneratedValue (Strategie = GenerationType.IDENTITY) Durch Hinzufügen dieser Anmerkung zur Primärschlüsseleigenschaft in Ihrer Entity-Bean sollte dieses Problem behoben werden.
quelle
Ich habe dieses Problem gelöst.
Tatsächlich geschieht dies, weil wir die Implementierung der PK-Eigenschaft Generator Type in der Bean-Klasse vergessen haben. Also mach es zu einem beliebigen Typ wie
Wenn wir die Objekte von Bean beibehalten, hat jedes Objekt dieselbe ID erhalten, sodass das erste Objekt gespeichert wird. Wenn ein anderes Objekt beibehalten
Exception: org.hibernate.NonUniqueObjectException:
werden soll, wurde der Sitzung bereits HIB FW über diesen Typ eines anderen Objekts mit demselben Bezeichnerwert zugeordnet.quelle
Das Problem tritt auf, weil Sie in derselben Ruhezustandssitzung versuchen, zwei Objekte mit derselben Kennung zu speichern. Es gibt zwei Lösungen:
Dies geschieht, weil Sie Ihre Mapping.xml-Datei für ID-Felder wie folgt nicht richtig konfiguriert haben: -
Überladen Sie die Methode getsession, um einen Parameter wie isSessionClear zu akzeptieren, und löschen Sie die Sitzung, bevor Sie die aktuelle Sitzung wie unten beschrieben zurückgeben
Dies führt dazu, dass vorhandene Sitzungsobjekte gelöscht werden. Auch wenn im Ruhezustand keine eindeutige Kennung generiert wird, sollte dies für Sie funktionieren, vorausgesetzt, Sie haben Ihre Datenbank mithilfe von Auto_Increment ordnungsgemäß für einen Primärschlüssel konfiguriert.
quelle
Ich hatte ein ähnliches Problem. In meinem Fall hatte ich vergessen, den
increment_by
Wert in der Datenbank auf den gleichen Wert wie den voncache_size
und festzulegenallocationSize
. (Die Pfeile zeigen auf die genannten Attribute)SQL:
Java:
quelle
Anders als von wbdarby gesagt, kann es sogar passieren, wenn ein Objekt abgerufen wird, indem die Kennung des Objekts einem HQL übergeben wird. Wenn Sie versuchen, die Objektfelder zu ändern und sie in derselben Sitzung wieder in der Datenbank zu speichern (Änderung kann Einfügen, Löschen oder Aktualisieren sein) , wird dieser Fehler angezeigt. Versuchen Sie, die Ruhezustandssitzung zu löschen, bevor Sie Ihr geändertes Objekt speichern, oder erstellen Sie eine brandneue Sitzung.
Hoffe ich habe geholfen ;-)
quelle
Ich habe den gleichen Fehler, bei dem ich mein Set durch ein neues von Jackson ersetzt habe.
Um dies zu lösen, behalte ich die vorhandene Menge bei und entferne aus der alten Menge das unbekannte Element in die neue Liste mit
retainAll
. Dann füge ich die neuen mit hinzuaddAll
.Sie müssen die Sitzung nicht haben und sie manipulieren.
quelle
Versuche dies. Das Folgende hat bei mir funktioniert!
In der
hbm.xml
DateiWir müssen das
dynamic-update
Attribut des Klassen-Tags auf Folgendes setzentrue
:Setzen Sie das Klassenattribut des Generator-Tags unter der eindeutigen Spalte auf
identity
:Hinweis: Setzen Sie die eindeutige Spalte auf
identity
anstatt aufassigned
.quelle
Eine andere Sache, die für mich funktioniert hat, war, die Instanzvariable Long anstelle von long zu machen
Ich hatte meine Primärschlüsselvariable lange ID; Ändern in Long id; hat funktioniert
Alles Gute
quelle
Sie können jederzeit eine Sitzungsspülung durchführen. Flush synchronisiert den Status aller Ihrer Objekte in der Sitzung (bitte korrigiert mich jemand, wenn ich falsch liege), und möglicherweise wird es in einigen Fällen Ihr Problem lösen.
Das Implementieren Ihrer eigenen Gleichheits- und Hashcodes kann Ihnen ebenfalls helfen.
quelle
Sie können Ihre Kaskadeneinstellungen überprüfen. Die Cascade-Einstellungen Ihrer Modelle könnten dies verursachen. Ich habe die Cascade-Einstellungen entfernt (Cascade Inserts / Updates sind im Wesentlichen nicht zulässig), wodurch mein Problem behoben wurde
quelle
Ich habe diesen Fehler auch gefunden. Was für mich funktioniert hat, ist sicherzustellen, dass der Primärschlüssel (der automatisch generiert wird) kein PDT (dh long, int, ect.) Ist, sondern ein Objekt (dh Long, Integer usw.).
Stellen Sie beim Erstellen Ihres Objekts zum Speichern sicher, dass Sie null und nicht 0 übergeben.
quelle
Hilft das?
quelle
Ich habe ein ähnliches Problem wie dieses gelöst:
quelle