0

my basic domain model looks like this : Domain Model

My problem exists with the mapping between the other Entities and the Attendance entity.

In Student i have tried :

@OneToMany(orphanRemoval=true,mappedBy = "student",cascade= CascadeType.ALL) 
    //@Cascade(org.hibernate.annotations.CascadeType.ALL)
    private Set<Attendance> attendance = new HashSet<Attendance>() ; 

on Attendance:

@ManyToOne( cascade= {CascadeType.PERSIST, CascadeType.MERGE} )
    //@Cascade(org.hibernate.annotations.CascadeType.PERSIST)
    @JoinColumn(name="studentId", nullable = true)
    private Student student;

    @OneToMany(mappedBy = "attendance",cascade=CascadeType.ALL)  
    private Set<Absence> absence = new HashSet<Absence>() ; 

    @ManyToOne()
    @JoinColumn(name="seminarId", nullable = false)
    private Seminar seminar;

    @OneToMany(mappedBy = "attendance",cascade=CascadeType.ALL)  
    private Set<Payment> payment = new HashSet<Payment>() ;

The problem i have is on the deletion of a Student(or a Seminar). What i want to do is, when a Student is deleted, all of his/her Attendances must be deleted too.

First I tested without creating any of the Absence or payment objects.

If I remove the cascade options i get the following trace

java.lang.IllegalStateException: org.hibernate.TransientObjectException: object is an unsaved transient instance - save the transient instance before merging: com.seminars.domain.Attendance

If i leave the cascade options and try to call em.remove(student) i get

javax.persistence.RollbackException: Error while committing the transaction
    ..........
Caused by: javax.persistence.EntityNotFoundException: deleted entity passed to persist: [com.seminars.domain.Student#<null>]

If above all this i try to add an absence to an attendance i still get the same as above( even though something tells me that even if student was removed something else would break)

I'm starting to believe that the domain model is completely wrong... Is it even possible to do what i want with JPA and hibernate ? What are the correct mapping options that i need to setup in my case ? (note: i also tried what is shown in this answer but then i had problems with attendance-absence

java.lang.IllegalStateException: org.hibernate.TransientObjectException: object is an unsaved transient instance - save the transient instance before merging: com.seminars.domain.Attendance

I am completely lost, any help would be greatly appreciated

EDIT: Below is the method for deleting a student ( please note that because em.remove(student); dint work, i resorted to manually delete the student. If i add an absence though, it is expected for the below code to not work. The real question is why em.remove() doesnt work, and what are the correct mappings that have to be set in order for it to work)

public void Delete(Object object) {
        int id=(Integer) object;
        if (!tx.isActive()) {
            tx.begin();
        } 
        Attendance att = em.find(Attendance.class, student.getStudentId());

        Query query = em.createQuery( "DELETE FROM Attendance c WHERE c.student = :id");
        query.setParameter("id", student);
        query.executeUpdate();
        em.clear();
        //findObject(null, id,null);
        //student=em.merge(student);
        //em.persist(student);
        student=em.find(Student.class, id);
        query = em.createQuery( "DELETE FROM Student c WHERE c.studentId = :id");
        query.setParameter("id", id);
        query.executeUpdate();
        //em.remove(student);

        tx.commit();
        //em.clear();
    }
Community
  • 1
  • 1
George
  • 418
  • 2
  • 9
  • 25
  • Show your delete codes – shazin Nov 30 '13 at 13:34
  • thank you for your reply. i added the code i used to delete the Student ( i did it like this and it worked before adding absence into the equation) – George Nov 30 '13 at 14:24
  • this really drives me crazy.. anything that can help is welcoming, even ideas you may think are not useful may help me. Everything that may help is welcomed :) – George Nov 30 '13 at 17:12

1 Answers1

0

The orphanRemoval=true option works only with JPA 2. If you work with an older version, you want to try the deprecated Hibernate annotation :

@Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

See the answers of the following question.

For you DAO, I would do something like:

@Component public class GenericDao {

@Resource(name = "sessionFactory")
private SessionFactory sessionFactory;

public <T> T save(final T o){
  return (T) sessionFactory.getCurrentSession().save(o);
}

public void delete(final Object object){
  sessionFactory.getCurrentSession().delete(object);
}

public <T> T get(final Class<T> type, final Long id){
  return (T) sessionFactory.getCurrentSession().get(type, id);
}

public <T> T merge(final T o)   {
  return (T) sessionFactory.getCurrentSession().merge(o);
}

}

Community
  • 1
  • 1
K.C.
  • 2,042
  • 2
  • 25
  • 36