У меня есть 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 пытается:
- вставка нового изображения (успешно)
- обновление существующего изображения (успешно)
- вставка записи в Join-Table / Collection-Table (chair_image) со ссылкой на стул и существующее изображение. Затем создается исключение JdbcSQLIntegrityConstraintViolationException, так как эта комбинация внешних ключей уже существует (старое изображение уже существовало ранее).
Почему это происходит и как мне это решить? Кажется, что сохранение и очистка изменений по отдельности внутри одной транзакции тоже не работает.