Коллекция приложений OneToMany пуста в приложении Hibernate
Я разрабатываю простой Hibernate
приложение для проверки OneToMany
ассоциация. Сущности, которые я использую Employee
а также Department
который имеет много Employees
:
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long departmentId;
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="department")
private Set<Employee> employees;
...
getters/setters
}
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long employeeId;
@ManyToOne
@JoinColumn(name="employee_fk")
private Department department;
...
getters/setters
}
Я создаю несколько записей с:
tx.begin();
Department department = new Department();
department.setDepartmentName("Sales");
session.persist(department);
Employee emp1 = new Employee("Ar", "Mu", "111");
Employee emp2 = new Employee("Tony", "Almeida", "222");
Employee emp3 = new Employee("Va", "Ka", "333");
emp1.setDepartment(department);
emp2.setDepartment(department);
emp3.setDepartment(department);
session.persist(emp1);
session.persist(emp2);
session.persist(emp3);
Set<Employee> emps = department.getEmployees();
emps.remove(emp2);
Однако в последней строке: emps.remove(emp2);
Я получаю NullPointerException
, emps
Коллекция именно null
, Я попытался изменить владельца ассоциации с:
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long departmentId;
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="department_fk")
private Set<Employee> employees;
...
getters/setters
}
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long employeeId;
@ManyToOne
@JoinColumn(name="department_fk", insertable=false, updatable=false)
private Department department;
...
getters/setters
}
Однако результат тот же. Почему Set
из Employees
не создан. Что нужно изменить, чтобы оно заработало?
2 ответа
Инициализируйте коллекцию самостоятельно, либо в конструкторе, либо указав начальное значение для поля.
Действительно, Hibernate инициализирует коллекцию пустой коллекцией, когда вы извлекаете объект из базы данных. Однако, когда вы создаете объект самостоятельно и сохраняете его, Hibernate не будет касаться созданного вами объекта, а только сохранит его, поэтому в этом случае он не будет инициализировать поле для вас.
Если вы хотите убедиться, что поле никогда не будет нулевым, что, я согласен, желательно, просто убедитесь в этом сами, даже до того, как сохранитесь.
Давайте внимательно посмотрим на ваш код:
Department department = new Department();
department.setDepartmentName("Sales");
session.persist(department);
Employee emp1 = new Employee("Ar", "Mu", "111");
Employee emp2 = new Employee("Tony", "Almeida", "222");
Employee emp3 = new Employee("Va", "Ka", "333");
emp1.setDepartment(department);
emp2.setDepartment(department);
emp3.setDepartment(department);
session.persist(emp1);
session.persist(emp2);
session.persist(emp3);
Set<Employee> emps = department.getEmployees();
Вы создали Department
, три Employees
, установите ссылку на это Department
для каждого Employee
и сохранил их.
Задавать emps
будет нулевым, потому что после того, как вы сохранили сотрудников в базе данных, вы не перезагрузили department
, Если вы измените код следующим образом:
....
session.persist(emp3);
department = session.get(Department.class, department.getDepartmentId());
Set<Employee> emps = department.getEmployees();
emps.remove(emp2);
Вы должны быть в порядке.
Еще один момент, который я хотел бы упомянуть, - ваше отношение между Department
а также Employees
являются mappedBy
Department
что буквально означает, что Department
скажем, "мастер" сущность и ее Employee
являются "рабами", или, если вы предпочитаете, Department
берет на себя все обязанности по ведению карт и ссылок. Но в своем коде, который я прокомментировал выше, вы возлагаете эту ответственность за отображение Employee
юридические лица. Вы можете изменить свой код таким образом:
department.add(emp1);
department.add(emp2);
department.add(emp2);
session.persist(department);
чтобы сделать Department
делать свою работу по поддержанию карт и ссылок.