Имею две таблицы DEPARTMENT и EMPLOYEE (первая родительская, а вторая - дочерняя). То есть, каждому департаменту соответствует список сотрудников (связь one-to-many). Сотрудники не могут существовать вне департамента, но может существовать департамент без сотрудников. По-этому, мне нужно чтобы при удалении департамента из таблицы DEPARTMENT удалялись соответствующие ему сотрудники с таблицы EMPLOYEE.
Реализовать это нужно с помощью Hibernate. Перепробовал уйму разных вариантов, но при выполнении операции получаю ошибку:
ERROR: Cannot delete or update a parent row: a foreign key constraint fails (`STAFF`.`EMPLOYEE`, CONSTRAINT `FK_ons3ycsifhocods0wpg7gym58` FOREIGN KEY (`department_id`) REFERENCES `DEPARTMENT` (`id`))
Вот исходники:
DepartmentEntity:
@Entity
@Table(name = "DEPARTMENT")
public class DepartmentDataSet implements Serializable {
@Id
@Column(name = "id", unique = true)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "name", unique = false, updatable = true, length = 45)
private String name;
@OneToMany(mappedBy = "departmentId", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval=true)
@OnDelete(action = OnDeleteAction.CASCADE)
private Set<EmployeeDataSet> employeesSet;
public DepartmentDataSet() {
}
public DepartmentDataSet(String name) {
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public Set<EmployeeDataSet> getEmployeesSet() {
return employeesSet;
}
public void setEmployeesSet(Set<EmployeeDataSet> employeesSet) {
this.employeesSet = employeesSet;
}
@Override
public String toString() {
return "UserDataSet{" + "id=" + id + "', name='" + name + '\'' + '}';
}
}
EmployeeEntity:
@Entity
@Table(name = "EMPLOYEE")
public class EmployeeDataSet implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "department_id", unique = false, updatable = true)
private int departmentId;
@Column(name = "age", unique = false, updatable = true)
private String age;
@Column(name = "type", unique = false, updatable = false)
private String type;
@Column(name = "name", unique = false, updatable = true, length = 25)
private String name;
@Column(name = "language", unique = false, updatable = true, length = 25)
private String language;
@Column(name = "methodology", unique = false, updatable = true, length = 25)
private String methodology;
public EmployeeDataSet() {
}
public EmployeeDataSet(String name, String type, String age, int department_id, String methodology,
String language) {
this.setName(name);
this.setType(type);
this.setAge(age);
this.setDepartmentId(department_id);
this.setMethodology(methodology);
this.setLanguage(language);
}
public EmployeeDataSet(int id, String name, String type, String age, int department_id, String methodology,
String language) {
this.setId(id);
this.setName(name);
this.setType(type);
this.setAge(age);
this.setDepartmentId(department_id);
this.setMethodology(methodology);
this.setLanguage(language);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDepartmentId() {
return departmentId;
}
public void setDepartmentId(int departmentId) {
this.departmentId = departmentId;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getMethodology() {
return methodology;
}
public void setMethodology(String methodology) {
this.methodology = methodology;
}
@Override
public String toString() {
return "UserDataSet{" +
"id=" + id +
", name='" + name + "', age='" + age +
", type='" + departmentId + '\'' + '}';
}
}
DepartmentDAO:
public void removeDepartment(String name) throws HibernateException {
session.beginTransaction();
String hql = "delete from DepartmentDataSet where name = :name";
Query query = session.createQuery(hql);
query.setString("name", name);
int rowCount = query.executeUpdate();
session.getTransaction().commit();
System.out.println(">>DepartmentDDAO removeDepartment: " + rowCount);
}
Если сделать метод removeDepartment так, как показано ниже, то почему-то все работает. Но мне нужно чтобы мой метод получал имя департамента, а не его id.
public void removeDepartment(int id) throws HibernateException {
session.beginTransaction();
session.delete(session.get(DepartmentDataSet.class, 3));
session.getTransaction().commit();
}
Буду рад любым подсказкам куда копать)
Аннотация @OneToMany(cascade = CascadeType.ALL)
срабатывает только при удалении конкретной записи методом session.delete
. У Вас другой случай - идёт удаление результатов SQL-выборки: метод delete
не вызывается, а в executeUpdate
отрабатывает "чистый" SQL
и функции СУБД. JPA
в этом процессе уже не участвует и никакие аннотации не уходят в СУБД вместе с SQL
-запросом.
Решить задачу можно двумя способами.
session.delete
.FOREIGN KEY
следует добавить ON DELETE CASCADE
.Виртуальный выделенный сервер (VDS) становится отличным выбором
При вводе строки состоящей не только из цифр происходит ошибка