Matt Watson created CAY-2792:
--------------------------------

             Summary: Fix Insertion Order For Reflexive DataObjects
                 Key: CAY-2792
                 URL: https://issues.apache.org/jira/browse/CAY-2792
             Project: Cayenne
          Issue Type: Bug
          Components: Core Library
    Affects Versions: 4.2.RC1, 4.2.RC2
         Environment: Java 17
            Reporter: Matt Watson


For terminology's sake, I assume _Reflexive_ refers to when you have 2 objects 
of the same Model, that are related, in this case, parent/child 
(ToOne/HasMany). If this assumption is incorrect we can rename the title.

For a little history on this, we never encountered this bug until we upgraded 
to {{4.2.RC1}}, and I recently tested on {{4.2.RC2}} and the bug still exists.

For a while I thought this was only a bug in our environment, thinking that our 
code was causing the issue because Cayenne has a passing test in 
{{CayenneDataObjectRelationshipsIT.testReflexiveRelationshipInsertOrder1}}. But 
as I got to digging, the error occurs when the parent also has a relationship 
to some "Other" object that is not of the same model.

My commit has a breaking test. I have not worked on a fix yet, but will begin 
investigating. I suspect it has to do with the work done in CAY-2571, but I am 
not certain yet.

The issue is that Cayenne randomly tries to commit the child record in front of 
the parent record, therefore the database throws a Foreign Key error, since the 
parent does not yet exist when the child is inserted. Because of this 
randomness, my breaking test attempts this process 100 times. You will also see 
another test that passes with the same Models but without setting the "ToOne" 
Other object.

here is a look at the code that "randomly" fails:
{code:java}
    public void addReflexiveParentAndChildWithOtherRelationshipOnParent() {
        // can add Reflexive Parent (that belongsTo Other) and Child,
        // we will do this 100 times, because it randomly does it 
correctly/incorrectly

        // given some "other" Object
        final Other other = context.newObject(Other.class);
        other.setName("OtherB");
        context.commitChanges();

        final int attempts = 100;
        int errors = 0;

        for (int i = 0; i < attempts; i++) {
            // when parent is created and associated to "Other"

            final Reflexive parent = context.newObject(Reflexive.class);
            parent.setName("parentB"+i);
            parent.setToOther(other);

            // and child is created and associated to "Parent"
            final Reflexive child = context.newObject(Reflexive.class);
            child.setName("childB"+i);
            child.setToParent(parent);

            try {
                context.commitChanges();
            } catch (final Exception e) {
                errors++;
                e.printStackTrace();
                context.rollbackChanges();
            }
        }

        // then no error occurred
        assertEquals(String.format("Failed on %s of %s attempts.", errors, 
attempts), 0, errors);
    }
{code}

 



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to