Searene
Searene

Reputation: 27654

TransientObjectException even if I set cascade=CascadeType.ALL

I've two classes:

Employee.java

@Entity
@Table
public class Employee {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne
    private Department department;

    public Employee() {}

    public Employee(String name, Department department) {
        this.name = name;
        this.department = department;
    }


    public Employee(String name) {
        this.name = name;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + ", department="
                + department.getName() + "]";
    }

}

Department.java

@Entity
@Table
public class Department {

    @Id
    @GeneratedValue
    private Long id;


    private String name;

    @OneToMany(mappedBy="department",cascade=CascadeType.ALL)
    private List<Employee> employees = new ArrayList<Employee>();

    public Department() {
        super();
    }
    public Department(String name) {
        this.name = name;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Employee> getEmployees() {
        return employees;
    }
    public void setEmployees(List<Employee> employees) {
        this.employees = employees;
    }
}

Then I tried to save department and employees in the main method:

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Department department = new Department("java");
//session.save(department); //throw org.hibernate.TransientObjectException if I comment the line

session.save(new Employee("Jakab Gipsz",department));
session.save(new Employee("Captain Nemo",department));

session.getTransaction().commit();

It didn't work. It throwed an error:

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.learn.hibernate.Department

But if I uncommented the line session.save(department);, everything worked fine. Why? I've already set cascade=CascadeType.ALL, so it was supposed to save department automatically without throwing any errors. Did I miss anything?

Upvotes: 0

Views: 624

Answers (3)

Bilal BBB
Bilal BBB

Reputation: 1164

When you save an Employee, the Department is not saved because there is no cascade. If you want that, you need to add a cascade in the Employee class.

@ManyToOne(cascade = CascadeType.save)
private Department department;

Upvotes: 1

This is because you create Employee in the field initializer, so if it is not overwritten with a managed Employee instance, Hibernate sees it as transient and throws the exception at flush time.

The solution is not to create it in the field initializer:

@OneToMany(mappedBy="department",cascade=CascadeType.ALL)
private List<Employee> employees;

also you have to follow James answer

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Department department = new Department("java");
deparmtment.getEmployees().add(new Employee("Jakab Gipsz",department));
deparmtment.getEmployees().add(new Employee("Captain Nemo",department));

session.save(department);

session.getTransaction().commit();

Upvotes: 0

Erveron
Erveron

Reputation: 1928

Your cascade is on Department. That means, you need to save Department instance with added Employee instances. Employees will be than saved.

Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();

Department department = new Department("java");
deparmtment.getEmployees().add(new Employee("Jakab Gipsz",department));
deparmtment.getEmployees().add(new Employee("Captain Nemo",department));

session.save(department);

session.getTransaction().commit();

Upvotes: 1

Related Questions