Hibernate ElementCollection / JoinTable IntegrityConstraintViolationException

问题描述 投票:0回答:1

我有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正在尝试:

  1. 成功插入新图像
  2. 成功更新现有图像
  3. 将引用椅子和现有图像的条目插入到Join-Table / Collection-Table(chair_image)中。然后,将抛出此JdbcSQLIntegrityConstraintViolationException,因为此外键组合已经存在(旧图像之前已经存在)。

为什么会这样,我该如何解决?在同一个事务中单独保存和清除更改似乎也不起作用。

java hibernate spring-boot spring-data-jpa persistence
1个回答
0
投票

一种解决方法,以防其他人遇到此问题:颠倒操作顺序:

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的错误不再发生。

© www.soinside.com 2019 - 2024. All rights reserved.