简体   繁体   中英

Bidirectional one to many JPA org.hibernate.exception.ConstraintViolationException

I have been getting this exception when trying to add the correct relationship data to the other side of the one to many join.

For some reason it is not picking up the car_id automatically

Here is my code.

Car model

@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);
  }
}

Car Photo Model

@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;
}

Repository @Repository public interface CarRepository extends CrudRepository { }

Persistence

...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);

Error Logs

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)

Any help would be appreciated.

Update

Thanks for all your great advice. I have updated my Car model as suggested by @Andronicus to the following:

@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;
    }

I am still getting


    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.

So I am unsure where hibernate is checking for equality as surely this should work?

Actually you need to remove both insertable = false and updatable = false from your mapping:

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

And override equals and hashCode methods for Car and CarPhoto entities to avoid duplicating entities. You can do this using lombok's @EqualsAndHashCode(callSuper = false) .

Because with only insertable=true you will be able to insert the entity, but this can violate unique constraint.

Remove insertable=false from your declaration @JoinColumn(name="car_id", insertable=false, updatable=false) . Because now you decline both set and update for field car_id

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM