복붙노트

[SPRING] Spring + Hibernate : 같은 식별자 값을 가진 다른 객체가 이미 세션과 연관되어있다.

SPRING

Spring + Hibernate : 같은 식별자 값을 가진 다른 객체가 이미 세션과 연관되어있다.

Spring과 Hibernate를 사용하는 내 응용 프로그램에서는 CSV 파일을 구문 분석하고 CSV 파일에서 레코드를 읽을 때마다 handleRow ()를 호출하여 db를 채 웁니다.

내 도메인 모델 :

Family <-> SubFamily <-> Locus는 모두 양방향 매핑입니다.

암호:

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

다음과 같은 방법을 사용하여 Locus에 Species를 할당합니다. DAO 계층에 간단히 액세스합니다.

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

Hibernate는 다음과 같은 에러를 낸다 :

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

어떤 팁?

해결법

  1. ==============================

    1.병합 ()을 사용하십시오. 예외는 현재 세션에서 전달중인 엔터티를 이미 인식하고 있음을 의미합니다. 그렇지 않은 경우 hashCode () 및 equals ()를 재정의 한 방법을 확인하십시오. 이는 다른 엔터티에 대해 다른 값을 반환해야합니다.

    병합 ()을 사용하십시오. 예외는 현재 세션에서 전달중인 엔터티를 이미 인식하고 있음을 의미합니다. 그렇지 않은 경우 hashCode () 및 equals ()를 재정의 한 방법을 확인하십시오. 이는 다른 엔터티에 대해 다른 값을 반환해야합니다.

  2. ==============================

    2.delete () 또는 update ()를 수행하는 경우에도이 문제가 발생할 수 있습니다. 이 문제는 DTO에서 아마 최대 절전 모드로 매핑 된 pojo를 직접 만들면 발생할 수 있습니다. 이 pojo는 이제 세션에 이미 존재하는 식별자와 동일한 식별자를 가지며 이로 인해 문제가 발생합니다.

    delete () 또는 update ()를 수행하는 경우에도이 문제가 발생할 수 있습니다. 이 문제는 DTO에서 아마 최대 절전 모드로 매핑 된 pojo를 직접 만들면 발생할 수 있습니다. 이 pojo는 이제 세션에 이미 존재하는 식별자와 동일한 식별자를 가지며 이로 인해 문제가 발생합니다.

    이제 두 가지 옵션이 있습니다. @Bozho가 말한 것을 수행하고 먼저 객체를 병합 ()하십시오. 그것은 업데이트를 처리합니다. 삭제하려면 merge ()에 의해 반환 된 객체를 가져 와서 삭제하십시오.

    다른 옵션은 먼저 객체의 ID를 사용하여 세션을 쿼리 한 다음 삭제하거나 업데이트하는 것입니다.

  3. ==============================

    3.나는 그렇게 결심했다 : 삭제 방법 :

    나는 그렇게 결심했다 : 삭제 방법 :

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

    업데이트 방법 :

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

    4.엔티티가 ID 열에 대해 GeneratedValue 주석을 가지고 있지 않을 때 이것을 보았습니다 :

    엔티티가 ID 열에 대해 GeneratedValue 주석을 가지고 있지 않을 때 이것을 보았습니다 :

    @GeneratedValue(strategy = GenerationType.AUTO)
    
  5. ==============================

    5.saveOrUpdate () 호출 후 evict () 객체를 세션에서 업데이트하는 경우 해당 객체의 hashCode 구현도 확인하십시오.

    saveOrUpdate () 호출 후 evict () 객체를 세션에서 업데이트하는 경우 해당 객체의 hashCode 구현도 확인하십시오.

  6. ==============================

    6.세션의 두 인스턴스를 만들었을 수도 있습니다.

    세션의 두 인스턴스를 만들었을 수도 있습니다.

    Session session = factory.openSession();
    

    한 함수에서 한 세션을 열고 다른 세션을 작성하여 다른 함수를 실행하면이 문제가 발생합니다.

  7. from https://stackoverflow.com/questions/2144697/spring-hibernate-a-different-object-with-the-same-identifier-value-was-alrea by cc-by-sa and MIT license