Akhil Prajapati
Akhil Prajapati

Reputation: 1281

Hibernate: CasecadeType.ALL vs {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH, CascadeType.REMOVE}

I have a simple hibernate OneToOne program. It consists of an Instructor class and an InstructorDetail class. OneToOne mapping is defined from Instructor to InstructorDetail. I am simply saving an object of Instructor class (which should also save InstructorDetail object due to cascading). Scenario is:

  1. When I am using CascadeType.ALL, it is working fine.

  2. However, when I am using an array with all possible Cascade Types (@OneToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH, CascadeType.REMOVE})), it is giving me the following error message:

object references an unsaved transient instance - save the transient instance before flushing: com.poc.entity.InstructorDetail

Please find below my code:

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

@Entity
@Table(name="instructor")
public class Instructor {

@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column(name="id")
private int id;

@Column(name="first_name")
private String firstName;

@Column(name="last_name")
private String lastName;

@OneToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH, CascadeType.REMOVE})
@JoinColumn(name="instructor_detail_id")
private InstructorDetail instructorDetail;

public Instructor() {

}

public Instructor(String firstName, String lastName) {
    super();
    this.firstName = firstName;
    this.lastName = lastName;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public InstructorDetail getInstructorDetail() {
    return instructorDetail;
}

public void setInstructorDetail(InstructorDetail instructorDetail) {
    this.instructorDetail = instructorDetail;
}

}

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

@Entity
@Table(name="instructor_detail")
public class InstructorDetail {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="id")
private int id;

@Column(name="youtube_channel", length=40)
private String youtubeChannel;

@Column(name="hobby", length=20)
private String hobby;

public InstructorDetail() {

}

public InstructorDetail(String youtubeChannel, String hobby) {
    super();
    this.youtubeChannel = youtubeChannel;
    this.hobby = hobby;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getYoutubeChannel() {
    return youtubeChannel;
}

public void setYoutubeChannel(String youtubeChannel) {
    this.youtubeChannel = youtubeChannel;
}

public String getHobby() {
    return hobby;
}

public void setHobby(String hobby) {
    this.hobby = hobby;
}




}

..

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.poc.entity.Instructor;
import com.poc.entity.InstructorDetail;

public class OneToOneDemo {

private static SessionFactory sessionFactory;

static {
    sessionFactory = new Configuration().configure("hibernate.cfg.xml")
                            .addAnnotatedClass(Instructor.class)
                            .addAnnotatedClass(InstructorDetail.class)
                            .buildSessionFactory();
}

public static void main(String...s) {

    InstructorDetail instructorDetail = new InstructorDetail("xyz/youtube.com","cooking");

    Instructor instructor = new Instructor("Bhupesh","Nimje");

    try {
        instructor.setInstructorDetail(instructorDetail);

        save(instructor);
    }
    finally {
        sessionFactory.close();
    }


}

public static void save(Instructor instructor) {
    Session session = null;
    try {
        session = sessionFactory.openSession();

        session.beginTransaction();

        session.save(instructor);

        session.getTransaction().commit();
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    finally {
        session.close();
    }
}

}

Upvotes: 4

Views: 2844

Answers (1)

Akhil Prajapati
Akhil Prajapati

Reputation: 1281

Finally I was able to crack it. The CascadeType enum we are using is of javax.persistence package. session.save() method, on the other hand, is an original Hibernate method that does not conform to JPA specifications and hence this inconsistency. However, if we do the same thing using session.persist() method, it will work like a charm.

Upvotes: 5

Related Questions