Как удалить взаимосвязанные объекты с помощью Hibernate

У меня есть два объекта. Пусть это будет компания и сотрудник.

CREATE TABLE company (
  company_id BIGINT(20) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  chief_id BIGINT(20) NOT NULL,
  PRIMARY KEY (company_id),
  CONSTRAINT fk_company_chief
    FOREIGN KEY (chief_id)
    REFERENCES employee (employee_id)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);

CREATE TABLE employee(
  employee_id BIGINT(20) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  company_id BIGINT(20) NOT NULL,
  PRIMARY KEY (employee_id),
  CONSTRAINT fk_employee_company
    FOREIGN KEY (chief_id)
    REFERENCES employee (company_id)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);

И мои классы выглядят так:

class Employee {
  long id;
  String name;
  Company company;
}

class Company{
  long id;
  String name;
  Employee chief;
}

Затем я хочу удалить компанию со всеми ее сотрудниками. Я делаю это в одной транзакции. Я получаю что-то вроде "java.sql.BatchUpdateException: Column 'chief_id' cannot be null"

Я могу удалить только после того, как один из столбцов станет нулевым. Например, «chief_id BIGINT(20) NULL», а затем сделать company.chief=null перед удалением.

В проекте мы не используем каскады Hibernate, и я не могу изменить каскады базы данных.

Мы используем MySql 5.0.

Мне нужно что-то вроде: отключить ограничения-> удалить сущность-> включить ограничения. Отключенное состояние должно быть доступно только в рамках текущей транзакции. Я думал, что это поведение по умолчанию.


person Zalivaka    schedule 10.05.2011    source источник
comment
вы не указали здесь аннотации JPA, какое отношение, я надеюсь, это 1.. * (Компания--Сотрудник), можете ли вы добавить nullable = true поверх аннотации, определенной для идентификатора в POJO, имеет смысл?   -  person Narayan    schedule 10.05.2011


Ответы (3)


Если ваша СУБД поддерживает это, вы можете объявить одно из ваших ограничений как deferrable initially deferred, чтобы оно проверялось в конце транзакции.

person axtavt    schedule 10.05.2011
comment
Мне нравится ваше решение! Однако мы используем Mysql 5.0, и я не могу его использовать. Спасибо! - person Zalivaka; 11.05.2011
comment
Интересно, как сохраняются эти взаимосвязанные данные, если MySql выполняет проверки сразу? - person Zalivaka; 11.05.2011

Вы должны использовать каскады Hibernate. Отключение/включение ограничений базы данных — это операция DDL, и она фиксируется немедленно, невозможно скрыть «отключенное состояние» от других транзакционных контекстов.

person Olaf    schedule 10.05.2011

Если вы не можете использовать каскады Hibernate, вы можете использовать фиктивную компанию (например, company_id=-1) и фиктивный главный объект Employee (employee_id=-1). DummyChief принадлежит компании DummyCompany, а руководителем DummyCompany является DummyChief.

Затем вы можете продолжить в следующем порядке:

1/ Удалить всех неглавных сотрудников Компании.

2/ Установите для главного сотрудника компании значение DummyChief (employee_id=-1)

3/ Удалить главного сотрудника.

4/ Удалить компанию Company.

person TBW    schedule 10.05.2011