我有3个这样的JPA实体以及相应的JPA存储库。
@Entity
public class ChairEntity {
...
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@CollectionTable(name = "chair_image")
private Set<ImageEntity> images = new HashSet<>();
...
}
@Entity
public class TableEntity {
...
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@CollectionTable(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);
...或同时更新同一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正在尝试:
为什么会这样,我该如何解决?在同一个事务中单独保存和清除更改似乎也不起作用。
一种解决方法,以防其他人遇到此问题:颠倒操作顺序:
chairEntity.getImages().add(new ImageEntity(...));
chairRepository.saveAndFlush(chairEntity);
chairEntity.getImages().stream().forEach(imageEntity -> {
imageEntity.setDescription("some other description");
}
chairRepository.save(chairEntity); // crashes
休眠模式执行SQL语句的顺序保持不变,但是由于两者之间的刷新,错误地插入Join-Table的错误不再发生。