glassfish
  1. glassfish
  2. GLASSFISH-879

Dependency issues if both sides of a ManyToMany are removed

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: 9.0pe
    • Fix Version/s: 9.1pe_dev
    • Component/s: entity-persistence
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      879
    • Status Whiteboard:
      Hide

      HIGH

      Show
      HIGH

      Description

      Allowing cascade remove to work on ManyToMany mappings is an extended feature
      that goes beyond the spec.

      There is an issue with the current implementation that could be addressed.

      When a bidirectional ManyToMany mapping is set-up, the non-owning side is set
      as read only.

      When we calculate commit order, we do not add any dependancies based on
      ManyToMany mappings. As a result, if the readOnly side is chosen to be deleted
      first in our commit order, we will not remove the entry from the relation table
      before removing the item. This will cause a constraint dependancy error on the
      database.

      Changing the order of the mappings in the commit order, could be as simple as
      changing the class name since the initial sort is done alphabetically.

      Fixing this should be a matter of adding a constraint dependancy from the
      Owning to the non-Owning side when we set up the mapping.

      This make simple cascade remove of ManyToMany mappings work. There will likely
      be some issues with cycles. (e.g. if you add a OneToOne mapping between the
      same to entities like in the relationship between Employee and Project in our
      advanced test model.) This issue is much more difficult to solve and is likely
      part of the reason, Cascade Delete on ManyToMany is not required by the
      specification.

        Issue Links

          Activity

          Hide
          pkrogh added a comment -

          Reprioritized based on BUG triage. P4 HIGH.

          Show
          pkrogh added a comment - Reprioritized based on BUG triage. P4 HIGH.
          Hide
          mf125085 added a comment -

          Starting.

          Show
          mf125085 added a comment - Starting.
          Hide
          mf125085 added a comment -

          The constraint violation for ManyToMany mappings has been fixed by cascading the
          delete to the owning side first. This doesn't address uni-directional OneToMany
          mappings, and a separate bug will be filed for uni-directional OneToMany.

          src/java/oracle/toplink/essentials/mappings/ForeignReferenceMapping.java:

          • shouldObjectDeleteCascadeToPart
          • Added, refactored the rules about object removal in one separate method
          • Changed previous logic from

          isPrivateOwned() || \
          !query.shouldCascadeOnlyDependentParts() || \
          query.shouldDependentObjectBeDeleted(object)
          to

          isPrivateOwned() || \
          query.shouldCascadeAllParts() || \
          query.shouldDependentObjectBeDeleted(object)

          I hope this makes the condition more obvious

          • Is called in preDelete for OneToOne, OneToMany, and ManyToManyMapping
          • shouldObjectModifyCascadeToPartsForPreDelete
          • Added "INTERNAL:" to JavaDoc

          src/java/oracle/toplink/essentials/mappings/ManyToManyMapping.java:

          • preDelete
          • Removed isReadOnly check, b/c delete should be cascaded to owning side
            from non-owning side
          • Now uses shouldObjectModifyCascadeToPartsForPreDelete
            shouldObjectModifyCascadeToPartsForPreDelete is overwritten here!
          • Jointable entries are only removed from owning side
          • Delete is not cascaded, if
            a) related object is already processed (preventing circles)
            b) object is not scheduled for removal
            (call to ForeignReferenceMapping.shouldObjectDeleteCascadeToPart)
          • shouldObjectModifyCascadeToPartsForPreDelete
          • Added, overwrites foreign key implementation in ForeignReferenceMapping,
            b/c non-/owning side check is based on read-only property for join table
            mappings

          src/java/oracle/toplink/essentials/mappings/ObjectReferenceMapping.java:

          • preDelete
          • Refactored delete check into
            ForeignReferenceMapping.shouldObjectDeleteCascadeToPart
          • postDelete
          • if (query.shouldCascadeOnlyDependentParts() || !isPrivateOwned()) {
            return;
            should be:
            if (query.shouldCascadeOnlyDependentParts() && !isPrivateOwned()) {
            return;

          Otherwise query.shouldCascadeOnlyDependentParts() will still return.

          src/java/oracle/toplink/essentials/mappings/OneToManyMapping.java:

          • preDelete
          • Refactored delete check into
            ForeignReferenceMapping.shouldObjectDeleteCascadeToPart
          Show
          mf125085 added a comment - The constraint violation for ManyToMany mappings has been fixed by cascading the delete to the owning side first. This doesn't address uni-directional OneToMany mappings, and a separate bug will be filed for uni-directional OneToMany. src/java/oracle/toplink/essentials/mappings/ForeignReferenceMapping.java: shouldObjectDeleteCascadeToPart Added, refactored the rules about object removal in one separate method Changed previous logic from isPrivateOwned() || \ !query.shouldCascadeOnlyDependentParts() || \ query.shouldDependentObjectBeDeleted(object) to isPrivateOwned() || \ query.shouldCascadeAllParts() || \ query.shouldDependentObjectBeDeleted(object) I hope this makes the condition more obvious Is called in preDelete for OneToOne, OneToMany, and ManyToManyMapping shouldObjectModifyCascadeToPartsForPreDelete Added "INTERNAL:" to JavaDoc src/java/oracle/toplink/essentials/mappings/ManyToManyMapping.java: preDelete Removed isReadOnly check, b/c delete should be cascaded to owning side from non-owning side Now uses shouldObjectModifyCascadeToPartsForPreDelete shouldObjectModifyCascadeToPartsForPreDelete is overwritten here! Jointable entries are only removed from owning side Delete is not cascaded, if a) related object is already processed (preventing circles) b) object is not scheduled for removal (call to ForeignReferenceMapping.shouldObjectDeleteCascadeToPart) shouldObjectModifyCascadeToPartsForPreDelete Added, overwrites foreign key implementation in ForeignReferenceMapping, b/c non-/owning side check is based on read-only property for join table mappings src/java/oracle/toplink/essentials/mappings/ObjectReferenceMapping.java: preDelete Refactored delete check into ForeignReferenceMapping.shouldObjectDeleteCascadeToPart postDelete if (query.shouldCascadeOnlyDependentParts() || !isPrivateOwned()) { return; should be: if (query.shouldCascadeOnlyDependentParts() && !isPrivateOwned()) { return; Otherwise query.shouldCascadeOnlyDependentParts() will still return. src/java/oracle/toplink/essentials/mappings/OneToManyMapping.java: preDelete Refactored delete check into ForeignReferenceMapping.shouldObjectDeleteCascadeToPart
          Hide
          mf125085 added a comment -

          I filed issue 2991 on the problem with uni-directional OneToMany relationships.

          Show
          mf125085 added a comment - I filed issue 2991 on the problem with uni-directional OneToMany relationships.
          Show
          mf125085 added a comment - Link to sources: http://fisheye5.cenqua.com/changelog/glassfish/?cs=MAIN:mf125085:20070509233341

            People

            • Assignee:
              mf125085
              Reporter:
              tware
            • Votes:
              1 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: