Весеннее удаление при загрузке не является каскадным, оно устанавливает для ключа foriegn значение NULL, а затем завершается с ошибкой с нулевым ограничением. - PullRequest
0 голосов
/ 02 ноября 2019

Используя deleteById при весенней загрузке с отношением один ко многим, генерируемый запрос пытается установить для внешнего ключа значение NULL в ссылочных объектах вместо их удаления. Я использую репозиторий по умолчанию deleteById

Я установил для Cascadetype значение ALL, а для OrpahnRemoval значение true для определения внешнего ключа в объекте, и я установил ON DELETE CASCADE в DDL, который создал таблицу. ,

Вот операция удаления в классе контроллера

@Transactional
@DeleteMapping("transferImage/{imageId}")
public void  deleteTransferImage(@PathVariable int imageId) {
    repository.deleteById(imageId);
}

Вот ссылка от родителя на дочернюю сущность

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, OrphanRemoval = true)
@JoinColumn(name = "TRANSFER_IMAGE_ID")
private List<TransferPartition> partitions = new ArrayList<>();

Вот определениевнешний ключ в дочернем объекте

@JsonIgnore
@ManyToOne
@JoinColumn(name = "TRANSFER_IMAGE_ID", referencedColumnName = "TRANSFER_IMAGE_ID")
private TransferImage image;

Вот DDL, использованный для создания двух таблиц

CREATE TABLE TRANSFER_IMAGE (
TRANSFER_IMAGE_ID       SERIAL CONSTRAINT TRANSFER_IMAGE_PK PRIMARY KEY,
IMAGE_NAME              VARCHAR(50) CONSTRAINT TRANSFER_IMAGE_NAME_UK UNIQUE NOT NULL ,
REQUESTED_PART_SIZE_MB  INTEGER NOT NULL,
SIZE_BYTES              INTEGER NOT NULL,
IMAGE_MD5_HASH          VARCHAR(100),
NUMBER_PARTITIONS       INTEGER,
DELETED                 BOOLEAN  NOT NULL
);

CREATE TABLE TRANSFER_PARTITION (
TRANSFER_PARTITION_ID   SERIAL CONSTRAINT TRANSFER_PARTITION_PK PRIMARY KEY,
TRANSFER_IMAGE_ID       INTEGER NOT NULL CONSTRAINT TRANSFER_PARTITION_IMAGE_FK REFERENCES TRANSFER_IMAGE ON DELETE CASCADE ON UPDATE CASCADE,
PARTITION_NUMBER        INTEGER NOT NULL,
PARTITION_MD5_HASH      VARCHAR(100) NOT NULL,
SIZE_BYTES              INTEGER NOT NULL
);

Вот запрос, который появляется в журнале

 Hibernate:
  select
    transferim0_.transfer_image_id as transfer1_13_0_,
    transferim0_.deleted as deleted2_13_0_,
    transferim0_.image_md5_hash as image_md3_13_0_,
    transferim0_.image_name as image_na4_13_0_,
    transferim0_.number_partitions as number_p5_13_0_,
    transferim0_.requested_part_size_mb as requeste6_13_0_,
    transferim0_.size_bytes as size_byt7_13_0_,
    partitions1_.transfer_image_id as transfer5_14_1_,
    partitions1_.transfer_partition_id as transfer1_14_1_,
    partitions1_.transfer_partition_id as transfer1_14_2_,
    partitions1_.transfer_image_id as transfer5_14_2_,
    partitions1_.partition_number as partitio2_14_2_,
    partitions1_.partition_md5_hash as partitio3_14_2_,
    partitions1_.size_bytes as size_byt4_14_2_
from
    transfer_image transferim0_
left outer join
   transfer_partition partitions1_
       on transferim0_.transfer_image_id=partitions1_.transfer_image_id
where
      transferim0_.transfer_image_id=?
Hibernate:
update
    transfer_partition
 set
     transfer_image_id=null
 where
     transfer_image_id=?

Я ожидал, что все дочерние объекты (TransferPartition), которые ссылаются на родителя (TransferImage), будут удалены при удалении родителя по его первичному ключу. Вместо этого я получаю нулевую ошибку ограничения, ссылающуюся на столбец внешнего ключа. Мне кажется, что сгенерированный SQL устанавливает пустой столбец внешнего ключа вместо удаления строки.

ERROR: null value in column "transfer_image_id" violates not-null constraint
Detail: Failing row contains (1, null, 1, asdfaa1-1, 20000000).

Если я удаляю изображение из таблицы Transfer_image из запроса psql, то каскад удаления удаляется правильно иуказанные разделы удаляются.

delete  from transfer_image i where i.transfer_image_id = 1

1 Ответ

1 голос
/ 02 ноября 2019

Ваша проблема в определении отношения внешнего ключа в классе TransferImage.

Вместо

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, OrphanRemoval = true)
@JoinColumn(name = "TRANSFER_IMAGE_ID")
private List<TransferPartition> partitions = new ArrayList<>();

следует использовать

@OneToMany(mappedBy="image", cascade = CascadeType.ALL, fetch = FetchType.EAGER, OrphanRemoval = true)
private List<TransferPartition> partitions = new ArrayList<>();

См. Такжеhttps://www.baeldung.com/hibernate-one-to-many

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...