OpenJPA
  1. OpenJPA
  2. OPENJPA-1400

Unable to persist a relationship to a detached Entity

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.2.1, 2.0.0-M3
    • Fix Version/s: 1.2.2, 1.3.0, 2.0.0-beta
    • Component/s: kernel
    • Labels:
      None

      Description

      I ran into a problem where OpenJPA is unable to persist a relationship from an attached Entity to a detached Entity. The problem occurs if the detached Entity does not have a DetachedState

      {openjpa.DetachState=loaded(DetachedStateField=false)}

      and the version is zero. When trying to flush the scenario described, the following exception is thrown by OpenJPA:

      <openjpa-2.0.0-SNAPSHOT-r422266:882172M nonfatal user error> org.apache.openjpa.persistence.InvalidStateException: Encountered unmanaged object in persistent field "org.apache.openjpa.persistence.detachment.model.NoDetachedStateEntityFieldAccess.relationship" during flush. However, this field does not allow cascade persist. Set the cascade attribute for this field to CascadeType.PERSIST or CascadeType.ALL (JPA annotations) or "persist" or "all" (JPA orm.xml), or enable cascade-persist globally, or manually persist the related field value prior to flushing. You cannot flush unmanaged objects or graphs that have persistent associations to unmanaged objects.

      This scenario should work, but OpenJPA incorrectly determines that the detached Entity was never actually a part of a persistence context. If version field is anything other than zero the flush of the relationship works as expected. This problem is in the enhanced bytecode we assume that when no StateManager is present a version of zero means that an Entity isn't detached.
      // Decompiled Entity bytecode
      public Boolean pcIsDetached()

      { if(pcStateManager != null) if(pcStateManager.isDetached()) return Boolean.TRUE; else return Boolean.FALSE; if(pcGetDetachedState() != null && pcGetDetachedState() != PersistenceCapable.DESERIALIZED) return Boolean.TRUE; if(_version != 0) return Boolean.TRUE; else return Boolean.FALSE; }

      I will attach a patch which recreates this problem and also provides a solution. My solution to this problem is to add a boolean to the enhanced bytecode to keep track of whether or not the version field has been set. This fixes the problem for most cases, but there are still holes. In addition to the patch, I'll also post two decompiled Entities. One of those is enhanced with the existing code and the other is with my proposed changes.

      Notes:

      • For the sake of time, I did not fix this problem when using unenhanced classes.
      • This problem still exists if the detached Entity has been serialized at any point.
      1. OPENJPA-1400.patch
        14 kB
        Rick Curtis
      2. decompiled_entities.zip
        4 kB
        Rick Curtis
      3. OPENJPA-1400-1.2.x.patch
        14 kB
        Rick Curtis

        Issue Links

          Activity

          Hide
          Rick Curtis added a comment -

          Changes committed to 1.2.x, 1.3.x, and trunk.

          Show
          Rick Curtis added a comment - Changes committed to 1.2.x, 1.3.x, and trunk.
          Hide
          Rick Curtis added a comment -

          Attaching 1.2.x patch.

          Show
          Rick Curtis added a comment - Attaching 1.2.x patch.
          Hide
          Rick Curtis added a comment -

          Attaching code changes, test case, and decompiled Entities.

          Show
          Rick Curtis added a comment - Attaching code changes, test case, and decompiled Entities.

            People

            • Assignee:
              Rick Curtis
              Reporter:
              Rick Curtis
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development