我有下一个实体:

    public class Delivery {
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "delivery_seq")
        @SequenceGenerator(
                name = "delivery_seq",
                sequenceName = "delivery_sequence",
                allocationSize = 1)
        private Long id;

        @OneToMany(fetch = FetchType.EAGER,
                   cascade = {CascadeType.ALL},
                   orphanRemoval = true)
        @JoinColumn(name = "delivery_id")
        private Set<DeliveryItem> items = new HashSet<>();
    }

    @Entity
    @Table(name = "delivery_status_history")
    public class DeliveryStatusHistory {

        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "history_of_delivery_status_seq")
        @SequenceGenerator(
                name = "history_of_delivery_status_seq",
                sequenceName = "history_of_delivery_status_sequence",
                allocationSize = 1)
        private Long id;

        @Column(name = "delivery_status")
        @Enumerated(EnumType.STRING)
        private DeliveryStatusEnum status;

        @JoinColumn(name = "delivery_id", referencedColumnName = "id")
        @ManyToOne
        private Delivery delivery;
    }


DeliveryDeliveryStatusHistory具有更多的字段,但是DeliveryDeliveryStatusHistory没有OneToMany。

DeliveryStatusHistoryDelivery具有ManyToOne关系。 DeliveryStatusHistory中的Delivery属性非空。

当我尝试更新items的内容时,出于某些原因,Hibernate尝试删除DeliveryStatusHistory中的链接

delivery.getItems().clear();
delivery.getItems.addAll(deliveryItems);
deliveryRepository.saveAndFlush(delivery);


错误:

2019-10-07 12:06:42.623  WARN 1 --- [   scheduling-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 23502
2019-10-07 12:06:42.623 ERROR 1 --- [   scheduling-1] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: null value in column "delivery_id" violates not-null constraint
  Detail: Failing row contains (2558, 86, null, null, APPROVED, 2019-10-07 06:15:45.80725+00).
  Where: SQL statement "UPDATE ONLY "public"."delivery_status_history" SET "delivery_id" = NULL WHERE $1 OPERATOR(pg_catalog.=) "delivery_id""
2019-10-07 12:06:42.623  INFO 1 --- [   scheduling-1] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2019-10-07 12:06:42.627 ERROR 1 --- [   scheduling-1] o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [delivery_id]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:297) ~[spring-orm-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:254) ~[spring-orm-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528) ~[spring-orm-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) ~[spring-tx-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) ~[spring-tx-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) ~[spring-tx-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:178) ~[spring-data-jpa-2.2.0.RC3.jar:2.2.0.RC3]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93) ~[spring-aop-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.0.RC2.jar:5.2.0.RC2]
    at com.sun.proxy.$Proxy134.saveAndFlush(Unknown Source) ~[na:na]
    at tech.lmru.cdsdrbridge.adeo.BDOUpdateService.updateDeliveryItems(BDOUpdateService.java:394) ~[classes/:1.4.0-RELEASE]
    at sun.reflect.GeneratedMethodAccessor167.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_212]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_212]
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) ~[spring-context-5.2.0.RC2.jar:5.2.0.RC2]
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.2.0.RC2.jar:5.2.0.RC2]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_212]


有任何想法吗?

最佳答案

您可能需要更改DeliveryItems的级联类型。我会给CascadeType.PERSIST一个机会。这样,当您清除项目时,不会破坏对DeliveryStatusHistory的引用。

CascadeType.PERSIST : cascade type presist means that save() or persist() operations cascade to related entities.
CascadeType.MERGE : cascade type merge means that related entities are merged when the owning entity is merged.
CascadeType.REFRESH : cascade type refresh does the same thing for the refresh() operation.
CascadeType.REMOVE : cascade type remove removes all related entities association with this setting when the owning entity is deleted.
CascadeType.DETACH : cascade type detach detaches all related entities if a “manual detach” occurs.
CascadeType.ALL : cascade type all is shorthand for all of the above cascade operations.` (ref: https://howtodoinjava.com/hibernate/hibernate-jpa-cascade-types/)

07-26 04:59