Following the instructions on: Cayenne How can I help? <https://cayenne.apache.org/how-can-i-help.html>
I have created a JIRA issue: https://issues.apache.org/jira/browse/CAY-2792 And a pull request that includes the breaking test (without a fix yet): https://github.com/apache/cayenne/pull/563 Has anyone else encountered this issue? Seems like it would be a common enough structure, but maybe I am mistaken. Here is the text from the JIRA issue: > 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.RC2and 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 > <https://issues.apache.org/jira/browse/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: > > 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); > } > > If you would like me to elaborate more on how we use this structure in in the real world application I can. Thanks for any help offered out there, as I begin digging on a solution. Cheers, Matt Watson m...@swarmbox.com <mailto:m...@swarmbox.com>