Spring + Hibernate: un object différent avec le même identifiant a déjà été associé à la session

Dans mon application, qui utilise Spring et Hibernate, j’parsing un fichier CSV et remplis la firebase database en appelant handleRow() chaque fois qu’un enregistrement est lu à partir du fichier CSV.

Mon modèle de domaine:

«Famille» a beaucoup de «Sous-famille»

La sous-famille a beaucoup de locus

un locus appartient à une espèce

Family SubFamily Locus sont tous des mappages bidirectionnels.

Code:

 public void handleRow(Family dummyFamily, SubFamily dummySubFamily, Locus dummyLocus) { //Service method which access DAO layers CommonService serv = ctx.getCommonService(); boolean newFamily=false; Family family=serv.getFamilyByFamilyId(dummyFamily.getFamilyId()); if(family==null){ newFamily=true; family=new Family(); family.setFamilyId(dummyFamily.getFamilyId()); family.setFamilyIPRId(dummyFamily.getFamilyIPRId()); family.setFamilyName(dummyFamily.getFamilyName()); family.setFamilyPattern(dummyFamily.getFamilyPattern()); family.setRifID(dummyFamily.getRifID()); } SubFamily subFamily = family.getSubFamilyBySubFamilyId( dummySubFamily.getSubFamilyId() ); if(subFamily==null){ subFamily=new SubFamily(); subFamily.setRifID(dummySubFamily.getRifID()); subFamily.setSubFamilyId(dummySubFamily.getSubFamilyId()); subFamily.setSubFamilyIPRId(dummySubFamily.getSubFamilyIPRId()); subFamily.setSubFamilyName(dummySubFamily.getSubFamilyName()); subFamily.setSubFamilyPattern(dummySubFamily.getSubFamilyPattern()); family.addSubFamily(subFamily); } //use the save reference, to update from GFF handler Locus locus = dummyLocus; subFamily.addLocus(locus); assignSpecies(serv,locus); //Persist object if(newFamily){ serv.createFamily(family); } else { serv.updateFamily(family); } } 

une espèce est assignée à un locus en utilisant la méthode suivante, qui accède simplement à la couche DAO:

 private void assignSpecies (CommonService serv, Locus locus) { Ssortingng locusId = locus.getLocusId(); Ssortingng speciesId = CommonUtils.getLocusSpecies(locusId, ctx.getSpeciesList()).getSpeciesId(); //Simply get Species object from DAO Species sp = serv.getSpeciesBySpeciesId(speciesId); locus.setSpecies(sp); } 

Hibernate donne l’erreur suivante:

 [INFO] Starting scheduled refresh cache with period [5000ms] Hibernate: insert into species (species_id, name) values (?, ?) Hibernate: insert into species (species_id, name) values (?, ?) Hibernate: insert into species (species_id, name) values (?, ?) ############################ROW#####################1 SubFamiyID#######RIF0005913 Hibernate: select this_.id as id1_0_, this_.family_id as family2_1_0_, this_.rif_iD as rif3_1_0_, this_.family_name as family4_1_0_, this_.family_ipr_id as family5_1_0_, this_.family_pattern as family6_1_0_ from family this_ where this_.family_id=? Creating NEW SubFamiyID#######RIF0005913 Hibernate: select this_.id as id3_0_, this_.species_id as species2_3_0_, this_.name as name3_0_ from species this_ where this_.species_id=? Hibernate: insert into family (family_id, rif_iD, family_name, family_ipr_id, family_pattern) values (?, ?, ?, ?, ?) Hibernate: insert into subfamily (sub_family_id, rif_iD, sub_family_name, sub_family_ipr_id, sub_family_pattern, family_id, sub_family_index) values (?, ?, ?, ?, ?, ?, ?) Hibernate: insert into locus (locus_id, refTrans_id, function, species_id, sub_family_id, sub_family_index) values (?, ?, ?, ?, ?, ?) Hibernate: update species set species_id=?, name=? where id=? Hibernate: update subfamily set family_id=?, sub_family_index=? where id=? Hibernate: update locus set sub_family_id=?, sub_family_index=? where id=? ############################ROW#####################2 SubFamiyID#######RIF0005913 Hibernate: select this_.id as id1_0_, this_.family_id as family2_1_0_, this_.rif_iD as rif3_1_0_, this_.family_name as family4_1_0_, this_.family_ipr_id as family5_1_0_, this_.family_pattern as family6_1_0_ from family this_ where this_.family_id=? Hibernate: select subfamilie0_.family_id as family7_1_, subfamilie0_.id as id1_, subfamilie0_.sub_family_index as sub8_1_, subfamilie0_.id as id0_0_, subfamilie0_.sub_family_id as sub2_0_0_, subfamilie0_.rif_iD as rif3_0_0_, subfamilie0_.sub_family_name as sub4_0_0_, subfamilie0_.sub_family_ipr_id as sub5_0_0_, subfamilie0_.sub_family_pattern as sub6_0_0_, subfamilie0_.family_id as family7_0_0_ from subfamily subfamilie0_ where subfamilie0_.family_id=? Hibernate: select locuslist0_.sub_family_id as sub5_1_, locuslist0_.id as id1_, locuslist0_.sub_family_index as sub7_1_, locuslist0_.id as id2_0_, locuslist0_.locus_id as locus2_2_0_, locuslist0_.refTrans_id as refTrans3_2_0_, locuslist0_.function as function2_0_, locuslist0_.sub_family_id as sub5_2_0_, locuslist0_.species_id as species6_2_0_ from locus locuslist0_ where locuslist0_.sub_family_id=? Hibernate: select species0_.id as id3_0_, species0_.species_id as species2_3_0_, species0_.name as name3_0_ from species species0_ where species0_.id=? Hibernate: select this_.id as id1_0_, this_.family_id as family2_1_0_, this_.rif_iD as rif3_1_0_, this_.family_name as family4_1_0_, this_.family_ipr_id as family5_1_0_, this_.family_pattern as family6_1_0_ from family this_ where this_.family_id=? Hibernate: select this_.id as id3_0_, this_.species_id as species2_3_0_, this_.name as name3_0_ from species this_ where this_.species_id=? Exception in thread "main" [INFO] Closing Compass [compass] org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session: [com.bigg.nihonbare.common.domain.Species#1]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.bigg.nihonbare.common.domain.Species#1] Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.bigg.nihonbare.common.domain.Species#1] at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:590) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70) at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507) at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499) at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:218) at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268) en [INFO] Starting scheduled refresh cache with period [5000ms] Hibernate: insert into species (species_id, name) values (?, ?) Hibernate: insert into species (species_id, name) values (?, ?) Hibernate: insert into species (species_id, name) values (?, ?) ############################ROW#####################1 SubFamiyID#######RIF0005913 Hibernate: select this_.id as id1_0_, this_.family_id as family2_1_0_, this_.rif_iD as rif3_1_0_, this_.family_name as family4_1_0_, this_.family_ipr_id as family5_1_0_, this_.family_pattern as family6_1_0_ from family this_ where this_.family_id=? Creating NEW SubFamiyID#######RIF0005913 Hibernate: select this_.id as id3_0_, this_.species_id as species2_3_0_, this_.name as name3_0_ from species this_ where this_.species_id=? Hibernate: insert into family (family_id, rif_iD, family_name, family_ipr_id, family_pattern) values (?, ?, ?, ?, ?) Hibernate: insert into subfamily (sub_family_id, rif_iD, sub_family_name, sub_family_ipr_id, sub_family_pattern, family_id, sub_family_index) values (?, ?, ?, ?, ?, ?, ?) Hibernate: insert into locus (locus_id, refTrans_id, function, species_id, sub_family_id, sub_family_index) values (?, ?, ?, ?, ?, ?) Hibernate: update species set species_id=?, name=? where id=? Hibernate: update subfamily set family_id=?, sub_family_index=? where id=? Hibernate: update locus set sub_family_id=?, sub_family_index=? where id=? ############################ROW#####################2 SubFamiyID#######RIF0005913 Hibernate: select this_.id as id1_0_, this_.family_id as family2_1_0_, this_.rif_iD as rif3_1_0_, this_.family_name as family4_1_0_, this_.family_ipr_id as family5_1_0_, this_.family_pattern as family6_1_0_ from family this_ where this_.family_id=? Hibernate: select subfamilie0_.family_id as family7_1_, subfamilie0_.id as id1_, subfamilie0_.sub_family_index as sub8_1_, subfamilie0_.id as id0_0_, subfamilie0_.sub_family_id as sub2_0_0_, subfamilie0_.rif_iD as rif3_0_0_, subfamilie0_.sub_family_name as sub4_0_0_, subfamilie0_.sub_family_ipr_id as sub5_0_0_, subfamilie0_.sub_family_pattern as sub6_0_0_, subfamilie0_.family_id as family7_0_0_ from subfamily subfamilie0_ where subfamilie0_.family_id=? Hibernate: select locuslist0_.sub_family_id as sub5_1_, locuslist0_.id as id1_, locuslist0_.sub_family_index as sub7_1_, locuslist0_.id as id2_0_, locuslist0_.locus_id as locus2_2_0_, locuslist0_.refTrans_id as refTrans3_2_0_, locuslist0_.function as function2_0_, locuslist0_.sub_family_id as sub5_2_0_, locuslist0_.species_id as species6_2_0_ from locus locuslist0_ where locuslist0_.sub_family_id=? Hibernate: select species0_.id as id3_0_, species0_.species_id as species2_3_0_, species0_.name as name3_0_ from species species0_ where species0_.id=? Hibernate: select this_.id as id1_0_, this_.family_id as family2_1_0_, this_.rif_iD as rif3_1_0_, this_.family_name as family4_1_0_, this_.family_ipr_id as family5_1_0_, this_.family_pattern as family6_1_0_ from family this_ where this_.family_id=? Hibernate: select this_.id as id3_0_, this_.species_id as species2_3_0_, this_.name as name3_0_ from species this_ where this_.species_id=? Exception in thread "main" [INFO] Closing Compass [compass] org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session: [com.bigg.nihonbare.common.domain.Species#1]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.bigg.nihonbare.common.domain.Species#1] Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.bigg.nihonbare.common.domain.Species#1] at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:590) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89) at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70) at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507) at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499) at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:218) at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268) 

Des conseils?

Utilisez merge() . L’exception signifie que la session en cours connaît déjà l’entité que vous passez. Sinon, vérifiez comment vous avez remplacé hashCode() et equals() – il devrait renvoyer des valeurs différentes pour différentes entités.

Vous pouvez également rencontrer ce problème si vous faites un delete() ou update() . Le problème est susceptible de se produire si vous créez vous-même le pojo hibernate-mappé, peut-être à partir d’un DTO. Ce pojo a maintenant le même identifiant que celui qui se trouve déjà dans la Session , ce qui pose problème.

Vous avez maintenant deux options. Faites ce que @Bozho a dit et commencez par merge() l’object. Cela prend en charge la mise à jour. Pour supprimer, prenez l’object renvoyé par merge() et supprimez-le.

L’autre option consiste à interroger d’abord la Session à l’aide de l’ID de l’object, puis à le supprimer ou à le mettre à jour.

Je l’ai résolu: sur la méthode de suppression:

  this.getHibernateTemplate().clear(); this.getHibernateTemplate().delete(obj); // Esta línea realiza el "commit" del comando this.getHibernateTemplate().flush(); 

Sur la méthode de mise à jour:

  this.getHibernateTemplate().merge(obj); // Esta línea realiza el "commit" del comando this.getHibernateTemplate().flush(); 

J’ai vu cela lorsqu’une entité n’a pas d’annotation GeneratedValue pour sa colonne ID:

 @GeneratedValue(strategy = GenerationType.AUTO) 

Si vous mettez à jour un object evict () depuis la session après l’appel à saveOrUpdate (), vérifiez également votre implémentation hashCode de l’object.