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 dept = (Dept) session.load(Dept.class, 5);
session.delete(dept);
<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": 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.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
java.lang.NullPointerException
at util.HibernateUtil.getSession(HibernateUtil.java:22)
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.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
public void validate(Mapping mapping) throws MappingException {
237: if ( getKey().isCascadeDeleteEnabled() && ( !isInverse() || !isOneToMany() ) ) {
238: throw new MappingException(
239: "only inverse one-to-many associations may use on-delete="cascade": "
240: + getRole() );
241: }
242: if ( !getKey().isValid( mapping ) ) {
243: throw new MappingException(
244: "collection foreign key mapping has wrong number of columns: "
245: + getRole()
246: + " type: "
247: + getKey().getType().getName() );
248: }
249: if ( !getElement().isValid( mapping ) ) {
250: throw new MappingException(
251: "collection element mapping has wrong number of columns: "
252: + getRole()
253: + " type: "
254: + getElement().getType().getName() );
255: }
Hibernate: delete from t_dept where d_id=?
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:172)
......................
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`tarena/emp_t`, CONSTRAINT `FK5C282BD499E420F` FOREIGN KEY (`did`) REFERENCES `t_dept` (`d_id`))
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2016)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1452)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
... 30 more
[解决办法]
inverse="false"去掉
[解决办法]
去掉 inverse="false"
[解决办法]