先说逻辑流程,再付上代码吧。逻辑流程为:
1、打开事务
2、删除表B及表A的信息(B为A的子表)
3、重新添加新的B表信息及A表信息
4、事务完成问题出现了:
删除了A表及B表信息后再重新添加A表信息时出现org.hibernate.NonUniqueObjectException,也救时主键冲突。
但是我已经删除了A表及B表的信息了啊,怎么会主键冲突的呢?(已经确认在事务中确实删除了数据——删除后在事务中进行查询,A表记录数为0)代码:
public void setStepsOfPro(SysDefpro obj) throws Exception {
Session sess = getSession();
Transaction ts = null;
try {
ts = sess.beginTransaction();
String hql="";
Query q;
//删除流程的步骤信息
hql="from SysDefsteps where sysDefpro.defproid=?";
q = sess.createQuery(hql);
q.setLong(0,obj.getDefproid());
System.out.println("obj.getDefproid()==="+obj.getDefproid());
List li=q.list();
SysDefsteps steps;
for(int i=0;i<li.size();i++) {
steps=(SysDefsteps)li.get(i);
String hql2="delete SysDefprosec where sysDefsteps.defstepsid=?";
Query q2 = sess.createQuery(hql2);
q2.setLong(0,steps.getDefstepsid());
System.out.println("steps.getDefstepsid()==="+steps.getDefstepsid());
q2.executeUpdate();
}
hql="delete SysDefsteps where sysDefpro.defproid=?";
q = sess.createQuery(hql);
q.setLong(0,obj.getDefproid());
q.executeUpdate();

//测试用代码,检查是否已经删除了数据
hql="from SysDefsteps where sysDefpro.defproid=?";
q = sess.createQuery(hql);
q.setLong(0,obj.getDefproid());
System.out.println("obj.getDefproid()==="+obj.getDefproid());
li=q.list();
System.out.println("size============="+li.size());


//循环更新步骤信息
SysDefprosecMan dpsm=new SysDefprosecMan();
SysDefstepsMan dsm=new SysDefstepsMan();
SysDefsteps tmpsteps;
Iterator it=obj.getSysDefstepses().iterator();
Iterator prosecsIt;
int orserNum=0;
while(it.hasNext()){
//取得步骤对象
tmpsteps=(SysDefsteps)it.next();
//设置步骤序列号
tmpsteps.setStepsorder(++orserNum);
//添加步骤信息
System.out.println("insert===="+tmpsteps.getDefstepsid());
dsm.insert(sess,tmpsteps);
//取得步骤部门关联表的迭代器,并循环添加关联信息
prosecsIt=tmpsteps.getSysDefprosecs().iterator();
while(prosecsIt.hasNext()){
dpsm.insert(sess,(SysDefprosec)prosecsIt.next());
}
}
ts.commit();
}
catch (Exception e){
if(ts!=null) {
ts.rollback();
}
throw e;
}
finally{
HibernateSessionFactory.closeSession();
}
}

解决方案 »

  1.   

    试试在第一段删除后执行session.flush()。Hibernate会自己决定相应操作的顺序,所以最后Hibernate的SQL执行顺序未必和你Java代码一致。通过flush可以强制之前的语句优先输出的
      

  2.   

    你应该把你的映射文件也贴出来...
    你查看了你已经删除A表的数据了,那你B表的数据你删了吗?//设置步骤序列号 
    tmpsteps.setStepsorder(++orserNum); 
    这样不如直接定义它自增了
      

  3.   

    你执行删除后,并没有立即更新到数据库,而是再执行后面的添加,都完成后再一起提交到数据库进行删除和插入,正如2楼所说一样Hibernate的SQL执行顺序未必和你Java代码一致,这样就可能出现主键冲突的异常了。用2楼所说的方法应该可以解决
      

  4.   

    感谢大家参与,正如2楼及4楼说的一样,session.flush()可以强制执行之前的语句。关于3楼的大哥,事情是这样的:
    B表时A表的子表,且有关联,所以A表删除的情况,B表肯定已经删除了。
    tmpsteps.setStepsorder(++orserNum); 不用自增是因为A表其实也是子表,1个A的父对象有N个A的对象,救是说可以有N个{1,2,3}这样的序列号,且是每次添加A的父对象时生成的。再次感谢大家。