it-swarm.com.de

Fehler im Ruhezustand: org.hibernate.NonUniqueObjectException: Der Sitzung wurde bereits ein anderes Objekt mit demselben Bezeichnerwert zugeordnet

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?

97
harshit

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

164
Michael Wiles

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.

18
Hein

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.

13
Rahul N

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.

8
Prashant Bari

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.

7
redzedi

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!

4
Frithjof

Ich bin auf dieses Problem gestoßen:

  1. Objekt löschen (mit HQL)
  2. Sofortiges Speichern eines neuen Objekts mit derselben ID

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();
4
wbdarby

Holen Sie sich das Objekt in der Sitzung, hier ein Beispiel:

MyObject ob = null;
ob = (MyObject) session.get(MyObject.class, id);
3
user372467

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);
}
2
TimP

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.

1
Ôrel

Das Problem tritt auf, weil Sie in derselben Hibernatsitzung versuchen, zwei Objekte mit derselben Kennung zu speichern. Es gibt zwei Lösungen:

  1. 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>
    
  2. Ü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.

1
Rahul Kumar

Ü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

1
Ayan Sarkar

@GeneratedValue (strategy = GenerationType.IDENTITY): Durch das Hinzufügen dieser Anmerkung zur Primärschlüsseleigenschaft in Ihrem Entity-Bean sollte dieses Problem behoben werden.

1
Jay

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.

1

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 ;-)

1

Versuche dies. Das unten arbeitete für mich!

In der hbm.xml-Datei

  1. Wir müssen das dynamic-update-Attribut des class-Tags auf true setzen:

    <class dynamic-update="true">
    
  2. 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.

1
Explorer_N

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.

1
Thupten

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.

1
DustinA

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.

1
cwap

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.

1
engtuncay

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 <-)
1
kaba713

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.

1
Pavan Kumar

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

0
user1609848

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.

0
caarlos0

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();
0
user3132194

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

0
Ashishakgupta

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.

0
Ankit Sharma

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.

0
vipin cp

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.

0
Nuwan

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.

0