Ich habe zwei Benutzerobjekte und versuche, das Objekt mit zu speichern
session.save(userObj);
Ich erhalte 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#[email protected]]
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, die session.clear()
vor dem Speichern zu machen, immer noch kein Glück.
Dies ist das erste Mal, dass ich das Sitzungsobjekt bekomme, wenn eine Benutzeranforderung kommt. Ich verstehe, warum das Objekt in der Sitzung vorhanden ist.
Irgendwelche Vorschläge?
Ich habe diesen Fehler oft gehabt und es kann ziemlich schwer zu finden sein ...
Im Grunde sagen wir aus dem Ruhezustand, dass Sie zwei Objekte haben, die denselben Identifier (denselben Primärschlüssel) haben, aber nicht dasselbe Objekt sind.
Ich würde vorschlagen, dass Sie Ihren Code aufschlüsseln, d. H. Die Bits auskommentieren, bis der Fehler beseitigt ist, und dann den Code zurücksetzen, bis er zurückkommt und Sie den Fehler finden sollten.
Dies geschieht meistens über kaskadierte Sicherungsvorgänge, wenn zwischen Objekt A und B eine Kaskadenspeicherung erfolgt, das Objekt B jedoch bereits mit der Sitzung verknüpft wurde, jedoch nicht in derselben Instanz von B.
Welchen Primärschlüsselgenerator verwenden Sie?
Der Grund, warum ich frage, ist, dass dieser Fehler damit zusammenhängt, wie Sie den Ruhezustand angeben, um den dauerhaften Zustand eines Objekts zu ermitteln (d. H. Ob ein Objekt dauerhaft ist oder nicht). Der Fehler kann auftreten, weil der Ruhezustand versucht, ein Objekt zu speichern, das bereits dauerhaft ist. Bei Verwendung von save hibernate wird versucht, dieses Objekt zu speichern, und möglicherweise gibt es bereits ein Objekt mit demselben Primärschlüssel, der der Sitzung zugeordnet ist.
Beispiel
Angenommen, Sie verfügen über ein Hibernate-Klassenobjekt für eine Tabelle mit 10 Zeilen, die auf einer Primärschlüsselkombination basieren (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 der Ruhezustand versucht, die Objekte in der Datenbank zu persistieren, werden 5 bereits entfernte Zeilen ohne Fehler hinzugefügt. Jetzt werden die verbleibenden 5 Zeilen, die bereits vorhanden sind, diese Ausnahme auslösen.
Der einfachste Ansatz wäre, zu überprüfen, ob Sie einen Wert in einer Tabelle, der Teil von etwas ist, aktualisiert/entfernt haben und später versuchen, dieselben Objekte erneut einzufügen
Dies ist nur ein Punkt, an dem der Ruhezustand mehr Probleme verursacht als gelöst. In meinem Fall gibt es viele Objekte mit der gleichen Kennung 0, da sie neu sind und keine haben. Die Datenbank generiert sie. Irgendwo habe ich gelesen, dass 0 Signale nicht gesetzt sind. Der intuitive Weg, sie zu beharren, besteht darin, über sie zu iterieren und den Winterschlaf zu sagen, um die Objekte zu speichern. Aber das kannst du nicht tun - "Natürlich solltest du wissen, dass der Winterschlaf so und so funktioniert, deshalb musst du ..." Also kann ich jetzt versuchen, Ids in Long anstatt Long zu ändern und schauen, ob es dann ist works . Am Ende ist es einfacher, dies mit einem einfachen Mapper selbst zu tun, denn Ruhezustand ist nur eine zusätzliche intransparente Belastung . Ein anderes Beispiel: Der Versuch, Parameter aus einer Datenbank zu lesen und sie in einer anderen Datenbank zu speichern, zwingt Sie dazu fast alle Arbeiten manuell erledigen. Wenn Sie es trotzdem tun müssen, ist die Verwendung des Ruhezustands eine zusätzliche Arbeit.
USe session.evict(object);
Die Funktion der evict()
-Methode wird verwendet, um eine Instanz aus dem Sitzungscache zu entfernen. Speichern Sie das Objekt zum ersten Mal, indem Sie die session.save(object)
-Methode aufrufen, bevor Sie das Objekt aus dem Cache entfernen. Aktualisieren Sie das Objekt auf die gleiche Weise, indem Sie session.saveOrUpdate(object)
oder session.update(object)
aufrufen, bevor Sie evict () aufrufen.
Dies kann vorkommen, wenn Sie dasselbe Sitzungsobjekt für Lesen und Schreiben verwendet haben. Wie? Angenommen, Sie haben eine Sitzung erstellt Sie haben einen Datensatz aus der Employee-Tabelle mit dem Primärschlüssel Emp_id = 101 gelesen Jetzt haben Sie den Datensatz in Java geändert. __ Personaldatensatz in der Datenbank . Wir haben die Sitzung hier nirgends geschlossen . Da das gelesene Objekt auch in der Sitzung bestehen bleibt. Es steht im Konflikt mit dem Objekt, das wir schreiben möchten. Daher kommt dieser Fehler.
Wie bereits erwähnt, stieß ich auf dieses Problem, als ich cascade=all
an beiden Enden einer one-to-many
-Beziehung hatte. Nehmen wir an, A -> B (Eins-zu-Viele von A und Viele-Zu-Eins von B) und wurde aktualisiert Instanz von B in A und dann Aufruf von saveOrUpdate (A), führte dies zu einer zyklischen Speicheranforderung, dh das Speichern von A löst das Speichern von B aus, das das Speichern von A ... und in der dritten Instanz als Entität (von A) auslöst Es wurde versucht, dem sessionPersistenceContext hinzugefügt zu werden, dass die duplicateObject-Ausnahme ausgelöst wurde.
Ich könnte es lösen, indem ich die Kaskade von einem Ende entferne.
Ich bin auch auf dieses Problem gestoßen und hatte Schwierigkeiten, den Fehler zu finden.
Das Problem, das ich hatte, war folgendes:
Das Objekt wurde von einem Dao mit einer anderen Hibernatsitzung gelesen.
Um diese Ausnahme zu vermeiden, lesen Sie einfach das Objekt erneut mit dem Dao, der dieses Objekt später speichern/aktualisieren wird.
so:
class A{
readFoo(){
someDaoA.read(myBadAssObject); //Different Session than in class B
}
}
class B{
saveFoo(){
someDaoB.read(myBadAssObjectAgain); //Different Session than in class A
[...]
myBadAssObjectAgain.fooValue = 'bar';
persist();
}
}
Ich hoffe, dass einige Leute viel Zeit sparen!
Ich bin auf dieses Problem gestoßen:
Ich löste es, indem ich die Ergebnisse nach dem Löschen löschte und den Cache löschte, bevor das neue Objekt gespeichert wurde
String delQuery = "DELETE FROM OasisNode";
session.createQuery( delQuery ).executeUpdate();
session.flush();
session.clear();
Holen Sie sich das Objekt in der Sitzung, hier ein Beispiel:
MyObject ob = null;
ob = (MyObject) session.get(MyObject.class, id);
Ich bin auf dieses Problem gestoßen, als ich ein Objekt gelöscht habe.
/**
* Deletes the given entity, even if hibernate has an old reference to it.
* If the entity has already disappeared due to a db cascade then noop.
*/
public void delete(final Object entity) {
Object merged = null;
try {
merged = getSession().merge(entity);
}
catch (ObjectNotFoundException e) {
// disappeared already due to cascade
return;
}
getSession().delete(merged);
}
Ich habe den gleichen Fehler, dass ich mein Set durch ein neues von Jackson ersetzt habe.
Um dieses Problem zu lösen, halte ich das vorhandene Set. Ich entferne das Element unknown mit retainAll
..__ aus der alten Gruppe und füge die neuen mit addAll
hinzu.
this.oldSet.retainAll(newSet);
this.oldSet.addAll(newSet);
Keine Notwendigkeit, die Sitzung zu haben und sie zu manipulieren.
Das Problem tritt auf, weil Sie in derselben Hibernatsitzung versuchen, zwei Objekte mit derselben Kennung zu speichern. Es gibt zwei Lösungen:
Dies geschieht, weil Sie Ihre mapping.xml-Datei nicht korrekt für ID-Felder wie folgt konfiguriert haben: -
<id name="id">
<column name="id" sql-type="bigint" not-null="true"/>
<generator class="hibernateGeneratorClass"</generator>
</id>
Überladen Sie die getsession-Methode, um einen Parameter wie isSessionClear, Zu akzeptieren, und löschen Sie die Sitzung, bevor Sie die aktuelle Sitzung wie folgt zurückgeben
public static Session getSession(boolean isSessionClear) {
if (session.isOpen() && isSessionClear) {
session.clear();
return session;
} else if (session.isOpen()) {
return session;
} else {
return sessionFactory.openSession();
}
}
Dadurch werden vorhandene Sitzungsobjekte gelöscht. Auch wenn der Ruhezustand keinen eindeutigen Bezeichner generiert. Vorausgesetzt, Sie haben die Datenbank für einen Primärschlüssel ordnungsgemäß konfiguriert, beispielsweise mit Auto_Increment. Dies sollte für Sie funktionieren.
Überprüfen Sie einfach die ID, ob sie null oder 0 braucht
if(offersubformtwo.getId()!=null && offersubformtwo.getId()!=0)
hinzufügen oder Aktualisieren, wenn der Inhalt vom Formular auf Pojo gesetzt wird
@GeneratedValue (strategy = GenerationType.IDENTITY): Durch das Hinzufügen dieser Anmerkung zur Primärschlüsseleigenschaft in Ihrem Entity-Bean sollte dieses Problem behoben werden.
Dieses Problem tritt auf, wenn wir dasselbe Sitzungsobjekt aktualisieren, mit dem wir das Objekt aus der Datenbank abgerufen haben.
Sie können die Mergemethode des Ruhezustands anstelle der Aktualisierungsmethode verwenden.
z.B. Verwenden Sie zuerst session.get () und dann session.merge (object). Diese Methode erzeugt kein Problem. Wir können auch die merge () -Methode verwenden, um Objekte in der Datenbank zu aktualisieren.
Ansonsten, waswbdarbygesagt hat, kann es sogar vorkommen, dass ein Objekt abgerufen wird, indem der HQL die Kennung des Objekts übergeben wird. Wenn Sie versuchen, die Objektfelder zu ändern und wieder in der Datenbank zu speichern (Änderung könnte Einfügen, Löschen oder Aktualisieren sein) über dieselbe Sitzung , wird dieser Fehler angezeigt. Deaktivieren Sie die Hibernatsitzung, bevor Sie Ihr modifiziertes Objekt speichern, oder erstellen Sie eine neue Sitzung .
Hoffe ich habe geholfen ;-)
Versuche dies. Das unten arbeitete für mich!
In der hbm.xml
-Datei
Wir müssen das dynamic-update
-Attribut des class-Tags auf true
setzen:
<class dynamic-update="true">
Setzen Sie das Klassenattribut des Generator-Tags unter eindeutige Spalte auf identity
:
<generator class="identity">
Anmerkung: Setzen Sie die eindeutige Spalte auf identity
statt auf assigned
.
Prüfen Sie, ob Sie vergessen haben, @GenerateValue für die @Id-Spalte zu setzen . Ich hatte das gleiche Problem mit vielen zu vielen Beziehungen zwischen Movie und Genre. Das Programm warf Ruhezustand-Fehler: org.hibernate.NonUniqueObjectException: Ein anderes Objekt mit demselben Bezeichnerwert war bereits mit der Sitzung verbunden @GenerateValue für die GenreId-Get-Methode.
Ich bin neu bei NHibernate und mein Problem war, dass ich eine andere Sitzung zum Abfragen meines Objekts verwendet habe als zum Speichern. Die Speichersitzung wusste also nichts über das Objekt.
Es ist offensichtlich, aber nachdem ich die vorherigen Antworten gelesen hatte, suchte ich überall nach 2 Objekten, nicht nach 2 Sitzungen.
Sind Ihre Id-Zuordnungen korrekt? Wenn die Datenbank für die Erstellung der ID durch einen Bezeichner verantwortlich ist, müssen Sie Ihr Benutzerobjekt diesem zuordnen.
bevor die Position beginnt, an der sich wiederholende Objekte beginnen, sollten Sie die Sitzung schließen und dann eine neue Sitzung beginnen
session.close();
session = HibernateUtil.getSessionFactory().openSession();
auf diese Weise gibt es in einer Sitzung nicht mehr als eine Entität mit derselben Kennung.
Ich hatte ein ähnliches Problem. In meinem Fall hatte ich vergessen, den increment_by
-Wert in der Datenbank so einzustellen, dass er dem von cache_size
und allocationSize
verwendeten Wert entspricht. (Die Pfeile zeigen auf die genannten Attribute)
SQL:
CREATED 26.07.16
LAST_DDL_TIME 26.07.16
SEQUENCE_OWNER MY
SEQUENCE_NAME MY_ID_SEQ
MIN_VALUE 1
MAX_VALUE 9999999999999999999999999999
INCREMENT_BY 20 <-
CYCLE_FLAG N
ORDER_FLAG N
CACHE_SIZE 20 <-
LAST_NUMBER 180
Java:
@SequenceGenerator(name = "mySG", schema = "my",
sequenceName = "my_id_seq", allocationSize = 20 <-)
Sie können session.merge(obj)
verwenden, wenn Sie das Speichern mit verschiedenen Sitzungen mit demselben beständigen Identifier-Objekt durchführen.
Es hat funktioniert, ich hatte das gleiche Problem vor.
Sie können Ihre Cascade-Einstellungen überprüfen. Die Cascade-Einstellungen Ihrer Modelle könnten dies verursachen. Ich habe die Cascade-Einstellungen (im Wesentlichen keine Cascade-Inserts/Updates erlaubt) entfernt. Dies hat mein Problem gelöst
Sie können immer einen Session-Flush durchführen. Der Flush synchronisiert den Status aller Ihrer Objekte in der Session (bitte korrigieren Sie mich, wenn ich falsch liege), und möglicherweise wird Ihr Problem in einigen Fällen gelöst.
Die Implementierung eigener Equals und Hashcodes kann auch Ihnen helfen.
Ich habe ein ähnliches Problem so gelöst:
plan = (FcsRequestPlan) session.load(plan.getClass(), plan.getUUID());
while (plan instanceof HibernateProxy)
plan = (FcsRequestPlan) ((HibernateProxy) plan).getHibernateLazyInitializer().getImplementation();
Hilft das?
User userObj1 = new User();
User userObj2 = userObj1;
.
.
.
rtsession.save(userObj1);
rtsession.save(userObj2);
Eine andere Sache, die sich für mich bewährt hat, war, die Instanz in Long anstelle von long zu ändern
Ich hatte meine Primärschlüsselvariable long id; In Long id; hat funktioniert
Alles Gute
Ich habe dieses Problem gelöst.
Tatsächlich geschieht dies, weil die Implementierung der Eigenschaft Generator Type of PK in der Bean-Klasse vergessen wurde. Also mache es wie jeder
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
wenn wir die Objekte des Beans persistieren, erhält jedes Objekt dieselbe ID. Das erste Objekt wird gespeichert. Wenn ein anderes Objekt persistent ist, wurde HIB FW durch diesen Typ von Exception: org.hibernate.NonUniqueObjectException:
bereits ein anderes Objekt mit demselben Bezeichnerwert der Sitzung zugeordnet.
Spät zur Party, kann aber für kommende Benutzer helfen -
Ich habe dieses Problem erhalten, wenn ich select einen Datensatz mit getsession()
und erneut update einen anderen Datensatz mit demselben Bezeichner benutze derselben Sitzung das Problem verursacht. Code unten hinzugefügt.
Customer existingCustomer=getSession().get(Customer.class,1);
Customer customerFromUi;// This customer details comiong from UI with identifer 1
getSession().update(customerFromUi);// Here the issue comes
Dies sollte niemals geschehen. Die Lösung besteht entweder aus einer Sitzung vor dem Update oder einer Änderung der Geschäftslogik.
Um dieses Problem zu lösen, versuchen Sie, das Objekt aus dem Ruhezustand-Cache/db zurückzulesen, bevor Sie Aktualisierungen vornehmen und dann beibehalten.
Beispiel:
OrderHeader oh = orderHeaderDAO.get(orderHeaderId);
oh.setShipFrom(facilityForOrder);
orderHeaderDAO.persist(oh);
Hinweis: Beachten Sie, dass dadurch die Hauptursache nicht behoben, das Problem jedoch behoben wird.
Ich habe auch diesen Fehler gefunden. Was für mich funktioniert hat, ist sicherzustellen, dass der Primärschlüssel (der automatisch generiert wird) keine PDT (d. H. Long, int, ect.) Ist, sondern ein Objekt (d. H. Long, Integer usw.).
Stellen Sie beim Erstellen Ihres Objekts zum Speichern sicher, dass Sie null und nicht 0 übergeben.