org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: test.Bottom.middle -> test.Middle

Hibernate JIRA | Carl-Eric Menzel | 7 years ago
  1. 0

    Given the following classes (pseudocode, full source in the attached zipfile): Top { @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "top") List<Middle> middles } Middle { @ManyToOne Top top @OneToOne(cascade = { CascadeType.ALL }) @JoinColumn(name = "BOTTOM_ID") Bottom bottom } Bottom { @OneToOne(mappedBy = "bottom") Middle middle } The following code fails on the second flush with a TransientObjectException: Top top = new Top(); em.persist(top); em.flush(); // top is now attached, status MANAGED Middle middle = new Middle(1l); middle.setBottom(new Bottom()); top.addMiddle(middle); Middle middle2 = new Middle(2l); middle2.setBottom(new Bottom()); top.addMiddle(middle2); // both middles and bottoms are transient but should be saved by cascade em.flush(); // boom! The relevant part of the error is: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: test.Bottom.middle -> test.Middle at org.hibernate.engine.CascadingAction$9.noCascade(CascadingAction.java:376) at org.hibernate.engine.Cascade.cascade(Cascade.java:163) The same code works without exception when using EclipseLink instead of Hibernate EntityManager, so I am assuming that the test code is valid. Some debugging revealed that CascadingAction.PERSIST_ON_FLUSH.noCascade() checks the inverse association from Bottom to Middle. It then calls a private method isInManagedState to verify that this association does not reference an unsaved instance. It does this by checking the entities EntityEntry.getStatus() value, which it expects to be MANAGED or READ_ONLY. At this time, however, the Middle instance is in the middle (no pun intended) of its own cascading save cycle and therefore its status is SAVING. This, to me, seems to be a valid session-attached status, so isInManagedState() should also accept this state. The attached patch against Hibernate Core 3.3.2 implements just that, and this change makes the above example code work as expected. The Hibernate test suite did not complain, so I am reasonably sure I did not break anything else. See also the attached cascadetest.zip for a ready-to-use testcase that demonstrates the error with Hibernate Core 3.3.2. Change the dependency in the supplied pom.xml to a patched version of Hibernate Core, and the test will no longer fail. Carl-Eric Menzel C1 SetCon GmbH

    Hibernate JIRA | 7 years ago | Carl-Eric Menzel
    org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: test.Bottom.middle -> test.Middle
  2. 0

    Given the following classes (pseudocode, full source in the attached zipfile): Top { @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "top") List<Middle> middles } Middle { @ManyToOne Top top @OneToOne(cascade = { CascadeType.ALL }) @JoinColumn(name = "BOTTOM_ID") Bottom bottom } Bottom { @OneToOne(mappedBy = "bottom") Middle middle } The following code fails on the second flush with a TransientObjectException: Top top = new Top(); em.persist(top); em.flush(); // top is now attached, status MANAGED Middle middle = new Middle(1l); middle.setBottom(new Bottom()); top.addMiddle(middle); Middle middle2 = new Middle(2l); middle2.setBottom(new Bottom()); top.addMiddle(middle2); // both middles and bottoms are transient but should be saved by cascade em.flush(); // boom! The relevant part of the error is: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: test.Bottom.middle -> test.Middle at org.hibernate.engine.CascadingAction$9.noCascade(CascadingAction.java:376) at org.hibernate.engine.Cascade.cascade(Cascade.java:163) The same code works without exception when using EclipseLink instead of Hibernate EntityManager, so I am assuming that the test code is valid. Some debugging revealed that CascadingAction.PERSIST_ON_FLUSH.noCascade() checks the inverse association from Bottom to Middle. It then calls a private method isInManagedState to verify that this association does not reference an unsaved instance. It does this by checking the entities EntityEntry.getStatus() value, which it expects to be MANAGED or READ_ONLY. At this time, however, the Middle instance is in the middle (no pun intended) of its own cascading save cycle and therefore its status is SAVING. This, to me, seems to be a valid session-attached status, so isInManagedState() should also accept this state. The attached patch against Hibernate Core 3.3.2 implements just that, and this change makes the above example code work as expected. The Hibernate test suite did not complain, so I am reasonably sure I did not break anything else. See also the attached cascadetest.zip for a ready-to-use testcase that demonstrates the error with Hibernate Core 3.3.2. Change the dependency in the supplied pom.xml to a patched version of Hibernate Core, and the test will no longer fail. Carl-Eric Menzel C1 SetCon GmbH

    Hibernate JIRA | 7 years ago | Carl-Eric Menzel
    org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: test.Bottom.middle -> test.Middle
  3. 0

    object references an unsaved transient instance - despite Cascade

    Stack Overflow | 4 years ago | Ben
    org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: EntityB.entityA -&gt; EntityA
  4. Speed up your debug routine!

    Automated exception search integrated into your IDE

  5. 0

    CascadeType.ALL does not work with one to many relationship

    Stack Overflow | 6 years ago | user725455
    org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.siemens.siguard.server.persistence.ejb.ResultGraphPoint.resultGraph -&gt; com.siemens.siguard.server.persistence.ejb.ResultGraph
  6. 0

    object references an unsaved transient instance

    Stack Overflow | 6 years ago | coubeatczech
    java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: cz.domain.model.PlayerInMatch.player -> cz.domain.model.Player

    1 unregistered visitors
    Not finding the right solution?
    Take a tour to get the most out of Samebug.

    Tired of useless tips?

    Automated exception search integrated into your IDE

    Root Cause Analysis

    1. org.hibernate.TransientObjectException

      object references an unsaved transient instance - save the transient instance before flushing: test.Bottom.middle -> test.Middle

      at org.hibernate.engine.CascadingAction$9.noCascade()
    2. Hibernate
      Cascade.cascade
      1. org.hibernate.engine.CascadingAction$9.noCascade(CascadingAction.java:376)
      2. org.hibernate.engine.Cascade.cascade(Cascade.java:163)
      2 frames