Как разрешить циклические ограничения внешнего ключа с NOT NULL в HibernateJAVA

Программисты JAVA общаются здесь
Anonymous
Как разрешить циклические ограничения внешнего ключа с NOT NULL в Hibernate

Сообщение Anonymous »

Я имею дело с проблемой циклической зависимости между двумя объектами (Store и Staff) в MySQL, которая вызывает проблемы при попытке сохранить данные с помощью Hibernate ORM (версия 6.6.0.Final, без Spring). Проблема возникает из-за ограничений внешнего ключа и NOT NULL в схеме базы данных.
Схема базы данных (MySQL)
Вот соответствующие разделы из моей базы данных. дамп: таблица:

Код: Выделить всё

CREATE TABLE `store` (
`store_id` tinyint unsigned NOT NULL AUTO_INCREMENT,
`manager_staff_id` tinyint unsigned NOT NULL,
`address_id` smallint unsigned NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`store_id`),
UNIQUE KEY `idx_unique_manager` (`manager_staff_id`),
KEY `idx_fk_address_id` (`address_id`),
CONSTRAINT `fk_store_address` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT `fk_store_staff` FOREIGN KEY (`manager_staff_id`) REFERENCES `staff` (`staff_id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
таблица:

Код: Выделить всё

CREATE TABLE `staff` (
`staff_id` tinyint unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`address_id` smallint unsigned NOT NULL,
`store_id` tinyint unsigned NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
`username` varchar(16) NOT NULL,
`password` varchar(40),
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`staff_id`),
KEY `idx_fk_store_id` (`store_id`),
KEY `idx_fk_address_id` (`address_id`),
CONSTRAINT `fk_staff_address` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`) ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT `fk_staff_store` FOREIGN KEY (`store_id`) REFERENCES `store` (`store_id`) ON DELETE RESTRICT ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Классы сущностей (Java)
Вот классы сущностей Java для Store и Staff:

Код: Выделить всё

Store.java
:

Код: Выделить всё

@Entity
@Table(schema = "movie", name = "store")
public class Store {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Short id;

@ManyToOne
@JoinColumn(name = "manager_staff_id", nullable = false)
private Staff mainStaff;

@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "address_id", nullable = false)
private Address address;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "mainStore")
private List staffList;

// other fields...
}

Код: Выделить всё

Staff.java
:

Код: Выделить всё

@Entity
@Table(schema = "movie", name = "staff")
public class Staff {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Short id;

@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "address_id", nullable = false)
private Address address;

@ManyToOne
@JoinColumn(name = "store_id", nullable = false)
private Store mainStore;

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "mainStaff")
private List stores;

// other fields...
}
Проблема
При попытке сохранить магазин или персонал я сталкиваюсь со следующим исключением:

Код: Выделить всё

java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation:
Caused by: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation:
Очевидно, что ограничение циклического внешнего ключа (

Код: Выделить всё

store.manager_staff_id
ссылается на Staff.staff_id и Staff.store_id ссылается на store.store_id) создает цикл зависимостей, который не позволяет мне сначала сохранить какой-либо объект. Я пробовал:
  • Удаление каскадирования и сохранение объектов вручную (не работает).
  • Попытка управлять транзакцией границ, чтобы гарантировать сохранение одного раньше другого, но циклическая зависимость вызывает ту же проблему.
Вопрос
Есть ли способ решить эту проблему в рамках использования Hibernate (без Spring)? Можно ли решить эту проблему исключительно на уровне ORM (сторона Java) без изменения схемы базы данных или ограничений (поскольку это находится вне моего контроля)?
Я ищу рекомендации по:
  • Правильная настройка каскадирования, если применимо.
  • Альтернативные способы разрешения циклической зависимости с соблюдением ограничений, налагаемых существующая схема MySQL.


Подробнее здесь: https://stackoverflow.com/questions/790 ... -hibernate

Вернуться в «JAVA»