Java Spring + Hibernate:具有相同标识符值的不同对象已经与会话相关联
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2144697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring + Hibernate : a different object with the same identifier value was already associated with the session
提问by Ashika Umanga Umagiliya
In my application, which uses Spring and Hibernate, I parse a CSV file and populate the db by calling handleRow()
every time a record is read from the CSV file.
在我的应用程序中,它使用 Spring 和 Hibernate,我解析一个 CSV 文件并通过handleRow()
每次从 CSV 文件读取记录时调用来填充数据库。
My domain model:
我的域模型:
'Family' has many 'SubFamily'
'SubFamily' has many 'Locus'
a 'Locus' belongs to a 'Species'
“家庭”有很多“子家庭”
'SubFamily' 有很多 'Locus'
一个“轨迹”属于一个“物种”
Family <-> SubFamily <-> Locus
are all bi-directional mappings.
Family <-> SubFamily <-> Locus
都是双向映射。
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);
}
}
a Species is assigned to a Locus using following method, which simply accesses the DAO layer:
使用以下方法将物种分配给轨迹,该方法只需访问 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 gives following error:
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.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
Any tips?
有小费吗?
采纳答案by Bozho
Use merge()
. The exception means that the current session is already aware of the entity you are passing. If not, check how you have overridden hashCode()
and equals()
- it should return different values for different entities.
使用merge()
. 异常意味着当前会话已经知道您正在传递的实体。如果没有,请检查你是如何覆盖hashCode()
和equals()
-它应该为不同的实体返回不同的值。
回答by Niel de Wet
You can also encounter this problem if you are doing a delete()
or update()
. The problem is likely to occur if you build the hibernate-mapped pojo yourself, perhaps from a DTO. This pojo now has the same identifier as one that is already in the Session
, and that causes the problem.
如果您正在执行 adelete()
或 ,您也可能会遇到此问题update()
。如果您自己构建 hibernate-mapped pojo,可能会发生此问题,可能来自 DTO。此 pojo 现在与 中已有的标识符具有相同的标识符Session
,这会导致问题。
You now have two options. Either do what @Bozho said and first merge()
the object. That takes care of updating. For deleting, take the object returned by merge()
and delete it.
您现在有两个选择。要么按照@Bozho 说的做,然后先做merge()
对象。这负责更新。对于删除,将返回的对象取出merge()
并删除。
The other option is to first query the Session
using the id of the object and then delete or update it.
另一种选择是首先Session
使用对象的 id查询,然后删除或更新它。
回答by Tom Chamberlain
I have seen this when an Entity does not have a GeneratedValue annotation for its ID column:
当实体的 ID 列没有 GeneratedValue 注释时,我已经看到了这一点:
@GeneratedValue(strategy = GenerationType.AUTO)
回答by Gabriel
I resolved so: On delete method:
我是这样解决的:关于删除方法:
this.getHibernateTemplate().clear();
this.getHibernateTemplate().delete(obj);
// Esta línea realiza el "commit" del comando
this.getHibernateTemplate().flush();
On update method:
关于更新方法:
this.getHibernateTemplate().merge(obj);
// Esta línea realiza el "commit" del comando
this.getHibernateTemplate().flush();
回答by Praveena DG
If you are updating an object evict() it from session after the saveOrUpdate() call, also check your hashCode implementation of the object.
如果您在 saveOrUpdate() 调用之后从会话中更新对象 evict() 它,还要检查您的对象的 hashCode 实现。
回答by Manas Ranjan Mahapatra
You may have created two instances of Session
您可能已经创建了两个实例 Session
Session session = factory.openSession();
If you have opened one session in one function and executing another function with creating another session, then this problem occurs.
如果您在一个函数中打开了一个会话并通过创建另一个会话执行另一个函数,则会出现此问题。
回答by Janac Meena
This happened to me because part of my compound key was null. Ex:
这发生在我身上,因为我的复合键的一部分是空的。前任:
@Id
@Column(name = "id")
private String id;
@JoinColumn(name = "id")
private Username username;
Username happened to be null which led to "duplicate" null primary keys, even though the id was different.
用户名碰巧为空,这导致“重复”空主键,即使 id 不同。