cayenne-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Hugi Thordarson <h...@karlmenn.is>
Subject Re: Exception when adding a new object to two different relationships
Date Tue, 12 Sep 2017 16:20:13 GMT
Hi NIkita,
thanks for the answer! I understand what the problem is and we decided to go back to sequences
for PK generation for now.

Cheers,
- hugi



> It's circular relationships with PKs generated by DB. This case Cayenne
> can't handle, as IDs become available only after insert and insert is
> impossible without these values as they are used for FKs.
> IIRC there was a discussion about this case somewhere, and solution will be
> really hard, something like insert first data without FK then update only
> FKs.
> Workaround is to split creation of objects and their linkage (you can wrap
> this in transaction to have atomicity).
> 
> On Fri, Sep 8, 2017 at 5:30 PM, Hugi Thordarson <hugi@karlmenn.is> wrote:
> 
>> Hi Amadeo,
>> thanks for the pointer. No, the reverse relationship doesn't matter (and
>> removing it doesn't help). I have now removed it in the github repo.
>> 
>> And this is reproducible in different projects, I just created this smalll
>> project to serve as an isolated runnable example.
>> 
>> - hugi
>> 
>> 
>>> On 8 Sep 2017, at 14:20, Amedeo Mantica <amedeomantica@me.com> wrote:
>>> 
>>> I see an untitledRel in the Model, it looks like to be a stub inverse
>> relationship... have you tried to remove it ?
>>> 
>>> Amedeo
>>> 
>>>> On 8 Sep 2017, at 14:05, Hugi Thordarson <hugi@karlmenn.is> wrote:
>>>> 
>>>> Hi all,
>>>> I'm encountering what I believe to be a bug, that someone more familiar
>> with Cayenne's internals than me might want to take a look at :)
>>>> 
>>>> In short: If I create a new DataObject, add it to two different
>> relationships on another object and then attempt to commit the whole
>> thing—it fails.
>>>> 
>>>> Consider the following code:
>>>> 
>>>> ObjectContext oc = createContext();
>>>> Person person = oc.newObject( Person.class );
>>>> Address address = oc.newObject( Address.class );
>>>> person.addToAddresses( address );
>>>> person.setLatestAddress( address );
>>>> 
>>>> oc.commitChanges();
>>>> 
>>>> This will result in the following exception:
>>>> 
>>>> Exception in thread "main" org.apache.cayenne.CayenneRuntimeException:
>> [v.4.1.M1-SNAPSHOT Aug 31 2017 12:03:09] Can't extract a master key.
>> Missing key (id), master ID (<ObjectId:Person, TEMP:00000058A5520119>)
>>>>     at org.apache.cayenne.access.DataDomainSyncBucket$
>> PropagatedValueFactory.get(DataDomainSyncBucket.java:290)
>>>>     at org.apache.cayenne.query.BatchQueryRow.getValue(
>> BatchQueryRow.java:64)
>>>>     at org.apache.cayenne.query.InsertBatchQuery$1.getValue(
>> InsertBatchQuery.java:63)
>>>>     at org.apache.cayenne.access.translator.batch.
>> InsertBatchTranslator.doUpdateBindings(InsertBatchTranslator.java:121)
>>>>     at org.apache.cayenne.access.translator.batch.
>> DefaultBatchTranslator.updateBindings(DefaultBatchTranslator.java:78)
>>>>     at org.apache.cayenne.access.jdbc.BatchAction.
>> runAsIndividualQueries(BatchAction.java:163)
>>>>     at org.apache.cayenne.access.jdbc.BatchAction.
>> performAction(BatchAction.java:87)
>>>>     at org.apache.cayenne.access.DataNodeQueryAction.runQuery(
>> DataNodeQueryAction.java:97)
>>>>     at org.apache.cayenne.access.DataNode.performQueries(
>> DataNode.java:293)
>>>>     at org.apache.cayenne.access.DataDomainFlushAction.runQueries(
>> DataDomainFlushAction.java:233)
>>>>     at org.apache.cayenne.access.DataDomainFlushAction.flush(
>> DataDomainFlushAction.java:153)
>>>>     at org.apache.cayenne.access.DataDomain.onSyncFlush(
>> DataDomain.java:633)
>>>>     at org.apache.cayenne.access.DataDomain.onSyncNoFilters(
>> DataDomain.java:603)
>>>>     at org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.
>> onSync(DataDomain.java:764)
>>>>     at org.apache.cayenne.tx.TransactionFilter$1.perform(
>> TransactionFilter.java:73)
>>>>     at org.apache.cayenne.tx.TransactionFilter$1.perform(
>> TransactionFilter.java:70)
>>>>     at org.apache.cayenne.tx.DefaultTransactionManager.
>> performInTransaction(DefaultTransactionManager.java:87)
>>>>     at org.apache.cayenne.tx.DefaultTransactionManager.
>> performInLocalTransaction(DefaultTransactionManager.java:59)
>>>>     at org.apache.cayenne.tx.DefaultTransactionManager.
>> performInTransaction(DefaultTransactionManager.java:52)
>>>>     at org.apache.cayenne.tx.DefaultTransactionManager.
>> performInTransaction(DefaultTransactionManager.java:40)
>>>>     at org.apache.cayenne.tx.TransactionFilter.onSync(
>> TransactionFilter.java:70)
>>>>     at org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.
>> onSync(DataDomain.java:764)
>>>>     at org.apache.cayenne.access.DataDomain.onSync(DataDomain.
>> java:590)
>>>>     at org.apache.cayenne.access.DataContext.flushToParent(
>> DataContext.java:742)
>>>>     at org.apache.cayenne.access.DataContext.commitChanges(
>> DataContext.java:691)
>>>>     at pktest.Main.main(Main.java:28)
>>>> 
>>>> 
>>>> 
>>>> If someone would like to have a look, I've created a project that
>> replicates the problem—just build it and run pktest.Main
>>>> 
>>>> https://github.com/hugith/pktest <https://github.com/hugith/pktest>
>>>> 
>>>> Cheers,
>>>> - hugi
>>> 
>> 
>> 
> 
> 
> -- 
> Best regards,
> Nikita Timofeev


Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message