我想问一下在hibernate,一对一关系映射能否进行级联删除,或者(单向外键,单向主键,双向外键,双向主键)中那些能进行级联删除?
    我写了一个一对一的双向外键关联的程序,为什么不能级联删除,具体代码如下
    
    有两张表Student和Address    Address实体
    package com.lh.entity;public class Address {
private int id;
private String address_detil;
private Student student;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAddress_detil() {
return address_detil;
}
public void setAddress_detil(String addressDetil) {
address_detil = addressDetil;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}    student实体
    package com.lh.entity;public class Student {
private int id;
private String name;
private Address address;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}    address.hbm.xml
    <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.lh.entity">
<class name="Address">
<id name="id" column="address_id">
<generator class="native" />
</id>
<property name="address_detil"/>
<one-to-one name="student" property-ref="address" cascade="delete" />
</class>
</hibernate-mapping>    student.hbm.xml
    <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="com.lh.entity">
<class name="Student">
<id name="id" column="student_id">
<generator class="native" />
</id>
<property name="name"/>
<many-to-one name="address" column="address_id" unique="true" />
</class>
</hibernate-mapping>
    添加一组数据
     @Test
public void testCreate(){
Session session=new Configuration().configure().buildSessionFactory().openSession();
Transaction t=session.beginTransaction();

Student s=new Student();
s.setName("晨曦");

Address a=new Address();
a.setAddress_detil("商丘市");
s.setAddress(a);

session.save(s);
session.save(a); session.getTransaction().commit();
session.close();
}
    想要级联删除改组数据,为什么按照下面这样写总是报错?
     @Test
public void testDeleteP(){
Session session=new Configuration().configure().buildSessionFactory().openSession();
Transaction t=session.beginTransaction();

Address a=new Address();
a.setId(1);

session.delete(a);

session.getTransaction().commit();
session.close();
}    报的错误为如下
    org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:262)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:183)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at com.lh.entity.Test11PK.testDeleteP(Test11PK.java:63)
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.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:73)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
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)
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails (`hibernate_zzti`.`student`, CONSTRAINT `FKF3371A1B85C7D94` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`))
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2018)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1454)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 32 more
    哪位大牛能帮我解决一下,小的感激不尽。

解决方案 »

  1.   

    一对一的这种情况下,其中一方要交出控制权,就是将其inverse属性设置为true。那个这一方就会依附于拥有控制权的一方
      

  2.   

      Address a=new Address();
            a.setId(1);
            
            session.delete(a);
            
    楼主级联删除的时候 先要加载
      Address a = (Address)session.load(Address.clss,1);
      session.delete(a);如果直接setId()直接把student表的外键置为null了,导致关联的丢失,删也删不彻底。
      

  3.   

    谢谢大家我已经解决了。
    3楼说的是对的
    因为直接创建一个Address a=new Address();a.setId(1);这样直接删Hibernate是无法找到外键关系的。
    只有先加载Address a = (Address)session.load(Address.clss,1);才能级联删除