Domanda Trovati riferimenti condivisi a una raccolta org.hibernate.HibernateException


Ho ricevuto questo messaggio di errore:

errore: trovati riferimenti condivisi a una raccolta: Person.relatedPersons

Quando ho provato a eseguire addToRelatedPersons(anotherPerson):

person.addToRelatedPersons(anotherPerson);
anotherPerson.addToRelatedPersons(person);

anotherPerson.save();
person.save();

Il mio dominio:

Person {

 static hasMany = [relatedPersons:Person];

}

Qualche idea del perché accada questo ?


44
2017-11-07 12:27


origine


risposte:


Hibernate mostra questo errore quando si tenta di mantenere più di un'istanza che condivide l'istanza stesso riferimento alla collezione (cioè l'identità della collezione in contrasto con l'uguaglianza delle collezioni).

Nota che significa lo stesso collezione, non elemento di raccolta - in altre parole relatedPersons su entrambi person e anotherPerson deve essere lo stesso Forse stai resettando quella raccolta dopo che le entità sono state caricate? O hai inizializzato entrambi i riferimenti con la stessa istanza di raccolta?


52
2017-11-07 20:04



Ho avuto lo stesso problema. Nel mio caso, il problema era che qualcuno usava BeanUtils per copiare le proprietà di un'entità in un'altra, così finimmo per avere due entità che facevano riferimento alla stessa collezione.

Dato che ho passato un po 'di tempo a indagare su questo problema, raccomanderei la seguente lista di controllo:

  • Cerca scenari come entity1.setCollection(entity2.getCollection()) e getCollection restituisce il riferimento interno alla raccolta (se getCollection () restituisce una nuova istanza della raccolta, non è necessario preoccuparsi).

  • Guarda se clone() è stato implementato correttamente.

  • Cercare BeanUtils.copyProperties(entity1, entity2).


40
2017-11-01 20:22



Spiegazione sulla pratica. Se provi a salvare il tuo oggetto, ad esempio:

Set<Folder> folders = message.getFolders();
   folders.remove(inputFolder);
   folders.add(trashFolder);
   message.setFiles(folders);
MESSAGESDAO.getMessageDAO().save(message);

non è necessario impostare l'oggetto aggiornato su un oggetto padre:

message.setFiles(folders);

Semplice salva il tuo oggetto genitore come:

Set<Folder> folders = message.getFolders();
   folders.remove(inputFolder);
   folders.add(trashFolder);
   // Not set updated object here
MESSAGESDAO.getMessageDAO().save(message);

4
2017-09-07 09:11



Nel mio caso, stavo copiando e incollando il codice dalle mie altre classi, quindi non ho notato che il codice getter era scritto male:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "credito")
public Set getConceptoses() {
    return this.letrases;
}

public void setConceptoses(Set conceptoses) {
    this.conceptoses = conceptoses;
}

Tutti i riferimenti conceptoses ma se guardi il get dice letrases


2
2018-06-23 21:21



Leggendo online la causa di questo errore può essere anche un bug ibernato, come soluzione che sembra funzionare, è per mettere un:

session.clear()

Devi mettere in chiaro dopo aver ottenuto i dati e prima di eseguire il commit e chiudere, vedi esempio:

//getting data
SrReq sr = (SrReq) crit.uniqueResult();
SrSalesDetailDTO dt=SrSalesDetailMapper.INSTANCE.map(sr);
//CLEAR            
session.clear();
//close session
session.getTransaction().commit();
session.close();
return dt;

Io uso questa soluzione per selezionare il database, per l'aggiornamento o l'inserimento non so se questa soluzione può funzionare o può causare problemi.

Il mio problema è uguale al 100% di questo: http://www.progtown.com/topic128073-hibernate-many-to-many-on-two-tables.html


1
2017-08-10 15:56



Anch'io ho avuto lo stesso problema, qualcuno ha usato BeanUtils.copyProperties(source, target). Qui sia l'origine che la destinazione stanno utilizzando la stessa collezione come attributo.

Quindi ho appena usato la copia profonda come di seguito ..

Come clonare la raccolta in Java - Copia profonda di ArrayList e HashSet


1
2017-07-25 12:28



Ho affrontato un'eccezione simile nella mia domanda. Dopo aver esaminato lo stacktrace era chiaro che l'eccezione era stata lanciata all'interno di a FlushEntityEventListener classe.

In Hibernate 4.3.7 il MSLocalSessionFactory il bean non supporta più il eventListeners proprietà. Quindi, è necessario recuperare esplicitamente il registro del servizio dai singoli bean di sessione di Hibernate e quindi impostare i listener di eventi personalizzati richiesti.

Durante l'aggiunta di listener di eventi personalizzati, è necessario assicurarsi che i corrispondenti listener di eventi predefiniti vengano rimossi dalla rispettiva sessione di sospensione.

Se il listener di eventi predefinito non viene rimosso, si verifica il caso di due listener di eventi registrati sullo stesso evento. In questo caso durante l'iterazione su questi listener, contro i primi ascoltatori, qualsiasi raccolta nella sessione verrà contrassegnata come raggiunta e mentre l'elaborazione della stessa raccolta contro il secondo listener genererebbe l'eccezione Hibernate.

Quindi, assicurati che durante la registrazione di listener personalizzati i listener predefiniti corrispondenti vengano rimossi dal registro.


0
2018-01-18 17:59



Considera un'entità:

public class Foo{
private<user> user;
/* with getters and setters */
}

E considera una classe di business logic:

class Foo1{
List<User> user = new ArrayList<>();
user = foo.getUser();
}

Qui l'utente e foo.getUser() condividere lo stesso riferimento. Ma il salvataggio dei due riferimenti crea un conflitto.

L'uso corretto dovrebbe essere:

class Foo1 {
List<User> user = new ArrayList<>();
user.addAll(foo.getUser);
}

Questo evita il conflitto.


-1
2017-08-07 09:32