首页 > 解决方案 > org.hibernate.PropertyValueException:非空属性引用空值或瞬态值

问题描述

我们任意收到了这个休眠错误
org.hibernate.PropertyValueException: not-null property references a null or transient value from production environment 但无法在本地生成。我已经给出了我们数据结构的一些伪代码和描述关系的代码。

class Parent {

   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   @JoinColumn(name = "parent_id")
   @OrderColumn(name = "idx")
   private List<ChildA> childAs;

   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   @JoinColumn(name = "parent_id")
   @OrderColumn(name = "idx")
   private List<ChildB> childBs;
}

class ChildB {

    @NotNull
    @JoinColumn(name = "child_a_id")
    @ManyToOne
    private ChildA childA;
}

此错误尤其发生在复制功能中,其中整个对象图从父级级联一次全部复制和持久化。</p>

void copy(Parent source) {

  Parent copy = makeCopy(source);

  entityManager.persist(copy);
}

Parent makeCopy(Parent source) {

  Parent destination = new Parent();

  // Set other properties

  destination.getChildAs().addAll(
        source.getChildAs()
                .stream()
                .map(a -> {
                  ChildA childA = new ChildA();
                  childA.setProperty(a.getProperty()); // copy properties
                  return childA;
                })
                .collect(Collectors.toList())
  );

  destination.getChildBs().addAll(
        source.getChildBs()
                .stream()
                .map(b -> {
                   ChildB childB = new ChildB();
                   childB.setProperty(b.getProperty()); // copy properties
                   childB.setChildA( 
                             findCopiedChildARefByUniqueProperty(
                                     destination.getChildAs(), 
                                     b.getChildA().getUniqueProperty()
                             )
                   )

                   return childB;
               })
              .collect(Collectors.toList())
);

...

  return destination;

}

它随机导致org.hibernate.PropertyValueException: not-null property references a null or transient value: ChildB.childA 在生产中运行时。

我已经检查了它在本地生成的休眠查询。为了在复制休眠时保存 ChildB 似乎总是首先插入具有空 childA 引用的 ChildB,然后插入 ChildA,然后用 childA 引用更新 childB,它在本地环境中没有任何问题。

生产错误堆栈跟踪:


org.hibernate.PropertyValueException: not-null property references a null or transient value: ChildB.childA
        at org.hibernate.engine.Nullability.checkNullability(Nullability.java:100)
        at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:312)
        at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
        at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:143)
        at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
        at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:201)
        at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:147)
        at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:799)
        at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:791)
        at org.hibernate.engine.EJB3CascadingAction$1.cascade(EJB3CascadingAction.java:48)
        at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
        at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:425)
        at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:362)
        at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:338)
        at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
        at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
        at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:475)
        at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:353)
        at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
        at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:143)
        at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
        at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:201)
        at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:147)
        at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:71)
        at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
        at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
        at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
        at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:839)

预先感谢您的任何帮助。

笔记:

'hibernate-core' version: '3.6.10.Final'

标签: hibernate

解决方案


推荐阅读