Search code examples
hibernateone-to-onehibernate-annotations

Delete using One to one relation in hibernate


Since I am new to hibernate and I am using hibernate 4 version. Following code contains simple example of one to one relationship using annotation. when I try to delete the parent object, throws foreign key constraint exception. I Am stuck and confused on how to achieve this. Eventhough i have used cascade type as all. Correct the mistakes

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;


   @Entity
   @Table(name="students")

public class Student {
@Id
@Column(name="student_id")
private long studentId=0;

@Column(name="sname",length=15)
private String studentName=null;

@Column(name="grp",length=15)
private String grp=null;

public long getStudentId() {
    return studentId;
}

public void setStudentId(long studentId) {
    this.studentId = studentId;
}

public String getStudentName() {
    return studentName;
}

public void setStudentName(String studentName) {
    this.studentName = studentName;
}

public String getGrp() {
    return grp;
}

public void setGrp(String grp) {
    this.grp = grp;
}
}

This is the Parent class used to insert and update in database.

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Id;
import javax.persistence.Table;


   @Entity
   @Table(name="address")

public class Address {
@Id
@Column(name="address_id")
private long addressId=0;

@Column(name="place",length=30)
private String place=null;

@OneToOne(targetEntity=Student.class,fetch=FetchType.EAGER , cascade=CascadeType.ALL, orphanRemoval=true)
@JoinColumn(name="stud_id",referencedColumnName="student_id")

private Student parent;

public long getAddressId() {
    return addressId;
}

public void setAddressId(long addressId) {
    this.addressId = addressId;
}

public String getPlace() {
    return place;
}

public void setPlace(String place) {
    this.place = place;
}

public Student getParent() {
    return parent;
}

public void setParent(Student parent) {
    this.parent = parent;
}
}

And following is the approach to delete the object. However I am getting the exception. How to delete child record which is associated with the parent object?.

public void deleteStudentDao(long studentId) throws Exception{
    Session session=null;
    try{

        if(studentId >0 && factory!=null 
                && !factory.isClosed()){
            session=factory.openSession();
            session.beginTransaction();

            Student student=new Student();
            student.setStudentId(studentId);

            Address address=new Address();
            address.setParent(student);

            session.delete(address);
            session.getTransaction().commit();
            System.out.println("The Student "+studentId+" detail deleted");
        }
    }catch(HibernateException e){
        session.getTransaction().rollback();
        throw e;
    }finally{
        if(session!=null){
            session.close();
        }
    }
}

Exception is

ERROR: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`address`, CONSTRAINT `FK_4ok3rcn3mnfl5ma2wuwvkluuo` FOREIGN KEY (`stud_id`) REFERENCES `students` (`student_id`))
    Mar 10, 2017 10:50:34 AM org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release
    INFO: HHH000010: On release of batch it still contained JDBC statements
    org.hibernate.exception.ConstraintViolationException: could not execute statement
        at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:72)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:62)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3400)
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3630)
    at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:114)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
    at com.mv.dao.StudentDetailDAO.deleteStudentDao(StudentDetailDAO.java:98)
    at com.mv.studentutil.StudentRelationalUtil.deleteStudentUtil(StudentRelationalUtil.java:56)
    at com.mv.studentmodifier.StudentModifier.main(StudentModifier.java:54)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`address`, CONSTRAINT `FK_4ok3rcn3mnfl5ma2wuwvkluuo` FOREIGN KEY (`stud_id`) REFERENCES `students` (`student_id`))
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:408)
    at com.mysql.jdbc.Util.getInstance(Util.java:383)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1049)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2840)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2334)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2262)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2246)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
    ... 15 more

Solution

  • You should not delete the address like that. You need to have bi-directional relationship between Student & Address in your case.

    @Entity
    @Table(name = "students")    
    public class Student {
        ...    
        // Add this property with getter & setter methods in your Student class. 
        @OneToOne(mappedBy="parent")
        private Address address; 
    
       ...
    
    }
    

    Now in your delete method get the Student entity from DB based on its Id, then get the student address from student entity, then delete the address entity. This deletes Address and Student because of cascade nature.

    Here is the code you can try with:

    try {
    
                if (studentId > 0 && factory != null && !factory.isClosed()) {
                    session = factory.openSession();
                    session.beginTransaction();
    
                    Student student = (Student) session.get(Student.class, studentId);
                    session.delete(student.getAddress());
    
                    /*Student student=new Student();
                    student.setStudentId(studentId);
    
                    Address address=new Address();
                    address.setParent(student);
    
                    session.delete(address);*/
    
                    session.getTransaction().commit();
                    System.out.println("The Student " + studentId + " detail deleted");
                }