Hibernate ElementCollection / JoinTable IntegrityConstraintViolationException - PullRequest
0 голосов
/ 08 января 2020

У меня есть 3 подобные JPA-сущности, а также соответствующие JPA-репозитории.

@Entity
public class ChairEntity {
  ...
  @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
  @JoinTable(name = "chair_image")
  private Set<ImageEntity> images = new HashSet<>();
  ...
}

@Entity
public class TableEntity {
  ...
  @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
  @JoinTable(name = "table_image")
  private Set<ImageEntity> images = new HashSet<>();
  ...
}


@Entity
public class ImageEntity{
  ...
  private String description;
  @Lob
  private byte[] data;
  ...
}

Используя REST-API, эти объекты создаются и обновляются. Обычно это работает нормально, например, я могу добавить несколько imageEntities одновременно, как это (все блоки кодов находятся внутри их собственной транзакции)

chairEntity.getImages().add(new ImageEntity(..));
chairEntity.getImages().add(new ImageEntity(..));
chairRepository.save(chairEntity);

... или обновить несколько ImageEntities одного и того же стулья сразу.

chairEntity.getImages().stream().forEach(imageEntity -> {
  imageEntity.setDescription("some other description");
}
chairRepository.save(chairEntity);

В обоих случаях все Изменения успешно каскадируются и сохраняются.

Если, однако, я обновляю существующую ImageEntity, а также добавляю другую сущность, происходит сбой:

chairEntity.getImages().stream().forEach(imageEntity -> {
  imageEntity.setDescription("some other description");
}
chairEntity.getImages().add(new ImageEntity(...));
chairRepository.save(chairEntity); // crashes

Исключение заключается в следующем (эквивалентная ошибка выдается с использованием h2db):

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "chair_image_pkey"

При проверке DB-Log кажется, что Hibernate пытается:

  1. вставка нового изображения (успешно)
  2. обновление существующего изображения (успешно)
  3. вставка записи в Join-Table / Collection-Table (chair_image) со ссылкой на стул и существующее изображение. Затем создается исключение JdbcSQLIntegrityConstraintViolationException, так как эта комбинация внешних ключей уже существует (старое изображение уже существовало ранее).

Почему это происходит и как мне это решить? Кажется, что сохранение и очистка изменений по отдельности внутри одной транзакции тоже не работает.

1 Ответ

0 голосов
/ 10 января 2020

Обходной путь, если кто-то еще сталкивается с этой проблемой: Обратный порядок операций:

chairEntity.getImages().add(new ImageEntity(...));
chairRepository.saveAndFlush(chairEntity);
chairEntity.getImages().stream().forEach(imageEntity -> {
  imageEntity.setDescription("some other description");
}
chairRepository.save(chairEntity); // crashes

Порядок, в котором Hibernate выполняет SQL -Statements, остается тем же, но из-за гриппа sh между, неисправная вставка в Join-Table больше не происходит.

...