Reputation: 27654
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
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
Reputation: 431
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
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