日期:2014-05-18  浏览次数:20674 次

hibernate级联删除,异常MappingException: only inverse one-to-many associations ...
本人初学hibernate,今天做级联删除,遇到两个问题。虽然第一个问题已经解决了,但是第二个问题让我调了一晚上。
我从第一个问题开始讲起:
一开始我是用主键做删除,结果总是删除了主表的记录,关联关系的表中只是改了外键值为null;
两张表是Dept和Emp,one-to-many关系
代码和配置大致是这样的:
	@Test
public void deleteDept(){
Session session = null;
try {
session = HibernateUtil.getSession();
session.setFlushMode(FlushMode.AUTO);
session.beginTransaction().begin();
Dept dept = new Dept();
dept.setId(1);
session.delete(dept);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtil.close(session);
}
}


<set cascade="all" lazy="extra" name="emps" inverse="false">
   <key  column="did"/>
    <one-to-many class="entity.Emp"/>
  </set>


这样只能删除一条dept的记录,跟他关联的emp中的外键只是被update成null而已。
后来查到,这是因为session删除时,必须删除一个从数据库中查询返回的Dept对象,不能new一个然后setId。于是我改成
Dept dept = (Dept) session.load(Dept.class, 5);
session.delete(dept);

这样,的确是没问题了。但是,我就是想要只通过一个主键值来做删除操作,要怎么办?

我还是在网上搜寻到,说只要增加配置属性on-delete="cascade"就可以了。于是我配置文件改成:
<set cascade="all" lazy="extra" name="emps" inverse="false">
   <key  column="did" on-delete="cascade"/>
    <one-to-many class="entity.Emp"/>
  </set>

结果就报出一个异常,org.hibernate.MappingException: only inverse one-to-many associations may use on-delete="cascade"
具体控制台打印如下:
org.hibernate.MappingException: only inverse one-to-many associations may use on-delete="cascade": entity.Dept.emps
at org.hibernate.mapping.Collection.validate(Collection.java:267)
at org.hibernate.mapping.Set.validate(Set.java:19)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1112)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1293)
at util.HibernateUtil.<clinit>(HibernateUtil.java:14)
at test.testEmp.deleteDept(testEmp.java:102)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.