java - 双向一对多 JPA org.hibernate.exception.ConstraintViolationException

标签 java spring database jpa java-8

当我尝试将正确的关系数据添加到一对多连接的另一端时,我遇到了此异常。

由于某种原因,它没有自动获取 car_id

这是我的代码。

车型

@Data
@Entity
@Table(uniqueConstraints={
  @UniqueConstraint(columnNames = {"date", "auctionNumber", "auctionId"})
})
public class Car {
  @Id
  @GeneratedValue
  private UUID id;

  private String date;

  private int auctionId;

  private int auctionNumber;

  @OneToMany(mappedBy = "car", orphanRemoval = true, cascade={CascadeType.ALL})
  private List<CarPhoto> photos;

  public void addPhoto(CarPhoto photo) {
    if (photos == null) {
      photos = new ArrayList<CarPhoto>();
    }
    photos.add(photo);
    photo.setCar(this);
  }
}

汽车照片模型

@Data
@Entity
@Table(name="car_photo")
public class CarPhoto {
  @Id
  @GeneratedValue
  private UUID id;

  @Column(unique=true)
  private String path;

  @ManyToOne(fetch=FetchType.LAZY)
  @JoinColumn(name="car_id", insertable=false, updatable=false)
  private Car car;
}

存储库 @存储库 公共(public)接口(interface) CarRepository 扩展 CrudRepository { }

坚持

...loop cardata {
    Car car = new Car();
    car.setAuctionId(cardata.auctionId);
    car.setAuctionNumber(cardata.auctionNumber);
    car.setDate(cardata.date);
    Pattern.compile("#").splitAsStream(cardata.pictures).forEach(path - > {
        CarPhoto photo = new CarPhoto();
        photo.setPath(path);
        car.addPhoto(photo);
    });
    cars.add(car);
}

carRepository.saveAll(cars);

错误日志

2019-02-24 21:16:32.086  WARN 52624 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 23502
2019-02-24 21:16:32.086 ERROR 52624 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: null value in column "car_id" violates not-null constraint
  Detail: Failing row contains (cec6e570-7ce9-4094-bbc1-32bcd732c695, pictures, null).
2019-02-24 21:16:32.086 ERROR 52624 --- [nio-8080-exec-1] o.h.i.ExceptionMapperStandardImpl        : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [car_id]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:296)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:536)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy101.saveAll(Unknown Source)
    at ivs.datacollection.GetCarHandler.endElement(GetCarHandler.java:121)

如有任何帮助,我们将不胜感激。

更新

感谢您提供的所有宝贵建议。我已按照 @Andronicus 的建议将我的汽车模型更新为以下内容:

@Data
@Entity
@Table(uniqueConstraints={
  @UniqueConstraint(columnNames = {"date", "auctionNumber", "auctionId"})
})
@EqualsAndHashCode(onlyExplicitlyIncluded = true, callSuper = false)
public class Car {

  @Id
  @GeneratedValue
  private UUID id;

  @EqualsAndHashCode.Include
  private String date;

  @EqualsAndHashCode.Include
  private int auctionId;

  @EqualsAndHashCode.Include
  private int auctionNumber;

  @OneToMany(mappedBy = "car", orphanRemoval = true, cascade={CascadeType.ALL})
  private List<CarPhoto> photos;

  public void addPhoto(CarPhoto photo) {
    if (photos == null) {
      photos = new ArrayList<CarPhoto>();
    }
    photos.add(photo);
    photo.setCar(this);
  }
}```

And CarPhoto model to:

```lang-java

    @Data
    @Entity
    @Table(name="car_photo")
    public class CarPhoto {
      @Id
      @GeneratedValue
      private UUID id;

      @Column(unique=true)
      private String path;

      @ManyToOne(fetch=FetchType.LAZY)
      @JoinColumn(name="car_id")
      private Car car;
    }

我还在继续


    Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "car_auction_id_auction_number_date_key"
      Detail: Key (auction_id, auction_number, date)=(236, 50024, 2019-02-28) already exists.

所以我不确定 hibernate 在哪里检查相等性,因为这肯定可以工作吗?

最佳答案

实际上,您需要从映射中删除 insertable = falseupdatable = false:

@JoinColumn(name="car_id", insertable=false, updatable=false)

并覆盖 CarCarPhoto 实体的 equalshashCode 方法,以避免重复实体。您可以使用 lombok 的 @EqualsAndHashCode(callSuper = false) 来完成此操作。

因为只有 insertable=true 您将能够插入实体,但这可能会违反唯一约束。

关于java - 双向一对多 JPA org.hibernate.exception.ConstraintViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54861382/

相关文章:

Java Paint 方法不绘制?

java - Java中的类似Python的装饰器?

spring - 使用sftp出站网关从远程目录获取文件列表

java - Oauth2 在 Spring Boot 中不起作用

php - 在编写查询时需要帮助

java - 从 csv 文件行创建 Java 对象的开销是多少

java - 如何获取对象的类型以便可以将其与 instanceof 一起使用?

Spring + Hibernate 保存()不工作

mysql - MessageBoardApp 的数据库结构

.NET TransactionScope 类和 T-SQL TRAN COMMIT 和 ROLLBACK