Hi Anthonin, A) Since you are using Oracle, you may need to use a DEFERRABLE constraint (INITIALLY DEFERRED).
B) Any reason you are using a custom PK generator instead of using the standard sequence generator supported by Cayenne? (Cayenne Modeler -> select DB Entity -> PK Generation Strategy -> Custom Sequence -> enter Sequence Name and Cache Size -- looks like you are using 1). mrg On Fri, Nov 5, 2021 at 5:44 AM Lize Anthonin (OceanOPS) <al...@groupcls.com> wrote: > Hi Michael, > > Thanks for your answer. > I tried, but does not seem to make any difference. I added > WeightedAshwoodEntitySorter (amongst other things) in a module loaded as > init-param for the CayenneFilter, as follows: > @Override > public void configure(Binder binder) { > binder.bind(RequestHandler.class) > .to(StatelessContextRequestHandler.class) > .withoutScope(); > > OraclePkGeneratorCustom pkgen = new OraclePkGeneratorCustom(); > pkgen.setPkCacheSize(1); > binder.bind(PkGenerator.class).toInstance(pkgen); > > > binder.bind(EntitySorter.class).to(WeightedAshwoodEntitySorter.class); > } > > And then the annotation as you mentioned on the child entity. It still > stays rather random... > > > Here is the stack trace, as you can see I use Cayenne 4.2.M3. That would > have been smarter of me to share it initially! > java.sql.SQLIntegrityConstraintViolationException: ORA-02291: integrity > constraint (JCOMMOPS_B.PTF_HARDWARE_FK) violated - parent key not found > > at > oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:509) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:461) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1104) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:553) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:269) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:655) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:270) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:91) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:970) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1205) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3666) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.T4CPreparedStatement.executeInternal(T4CPreparedStatement.java:1426) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.OraclePreparedStatement.executeLargeUpdate(OraclePreparedStatement.java:3756) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3736) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1063) > ~[ojdbc10-19.12.0.0.jar:19.12.0.0.0] > at > org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:136) > ~[tomcat-dbcp.jar:9.0.40] > at > org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:136) > ~[tomcat-dbcp.jar:9.0.40] > at > org.apache.cayenne.access.jdbc.BatchAction.runAsIndividualQueries(BatchAction.java:185) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.jdbc.BatchAction.performAction(BatchAction.java:96) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataNodeQueryAction.runQuery(DataNodeQueryAction.java:97) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataNode.performQueries(DataNode.java:273) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.flush.DefaultDataDomainFlushAction.lambda$executeQueries$6(DefaultDataDomainFlushAction.java:177) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at java.util.HashMap.forEach(HashMap.java:1425) ~[?:?] > at > org.apache.cayenne.access.flush.DefaultDataDomainFlushAction.executeQueries(DefaultDataDomainFlushAction.java:176) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.flush.DefaultDataDomainFlushAction.flush(DefaultDataDomainFlushAction.java:89) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataDomain.onSyncFlush(DataDomain.java:637) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataDomain.onSyncNoFilters(DataDomain.java:609) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:835) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.tx.TransactionFilter.lambda$onSync$0(TransactionFilter.java:61) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.tx.DefaultTransactionManager$BaseTransactionHandler.performInTransaction(DefaultTransactionManager.java:180) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.tx.DefaultTransactionManager$BaseTransactionHandler.performInNewTransaction(DefaultTransactionManager.java:152) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.tx.DefaultTransactionManager$NestedTransactionHandler.handle(DefaultTransactionManager.java:95) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:62) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.tx.DefaultTransactionManager.performInTransaction(DefaultTransactionManager.java:40) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.tx.TransactionFilter.onSync(TransactionFilter.java:61) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataDomain$DataDomainSyncFilterChain.onSync(DataDomain.java:834) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataDomain.onSync(DataDomain.java:596) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataContext.flushToParent(DataContext.java:737) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at > org.apache.cayenne.access.DataContext.commitChanges(DataContext.java:686) > ~[cayenne-server-4.2.M3.jar:4.2.M3] > at org.oceanops.api.id.IdGenerator.commitChanges(IdGenerator.java:47) > ~[classes/:?] > at > org.oceanops.api.id.WebServiceManager.getID(WebServiceManager.java:56) > ~[classes/:?] > at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native > Method) ~[?:?] > at > jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > ~[?:?] > at > jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > ~[?:?] > at java.lang.reflect.Method.invoke(Method.java:564) ~[?:?] > at > org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory.lambda$static$0(ResourceMethodInvocationHandlerFactory.java:52) > ~[jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:124) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:167) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:219) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:79) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:475) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:397) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:81) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:255) > [jersey-server-2.35.jar:?] > at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248) > [jersey-common-2.35.jar:?] > at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244) > [jersey-common-2.35.jar:?] > at org.glassfish.jersey.internal.Errors.process(Errors.java:292) > [jersey-common-2.35.jar:?] > at org.glassfish.jersey.internal.Errors.process(Errors.java:274) > [jersey-common-2.35.jar:?] > at org.glassfish.jersey.internal.Errors.process(Errors.java:244) > [jersey-common-2.35.jar:?] > at > org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265) > [jersey-common-2.35.jar:?] > at > org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684) > [jersey-server-2.35.jar:?] > at > org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394) > [jersey-container-servlet-core-2.35.jar:?] > at > org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346) > [jersey-container-servlet-core-2.35.jar:?] > at > org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:366) > [jersey-contain[apache-tomcat-9.0.40]: er-servlet-core-2.35.jar:?] > at > org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:319) > [jersey-container-servlet-core-2.35.jar:?] > at > org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205) > [jersey-container-servlet-core-2.35.jar:?] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > [catalina.jar:9.0.40] > at > org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) > [tomcat-websocket.jar:9.0.40] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > [catalina.jar:9.0.40] > at > org.oceanops.api.filters.AuthFilter.doFilter(AuthFilter.java:40) > [api-1.3-SNAPSHOT-classes.jar:?] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > [catalina.jar:9.0.40] > at > org.apache.cayenne.configuration.web.CayenneFilter.doFilter(CayenneFilter.java:127) > [cayenne-web-4.2.M3.jar:4.2.M3] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) > [catalina.jar:9.0.40] > at > org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) > [catalina.jar:9.0.40] > at > org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) > [catalina.jar:9.0.40] > at > org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690) > [catalina.jar:9.0.40] > at > org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) > [catalina.jar:9.0.40] > at > org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) > [catalina.jar:9.0.40] > at > org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) > [tomcat-coyote.jar:9.0.40] > at > org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) > [tomcat-coyote.jar:9.0.40] > at > org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:880) > [tomcat-coyote.jar:9.0.40] > at > org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1601) > [tomcat-coyote.jar:9.0.40] > at > org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) > [tomcat-coyote.jar:9.0.40] > at > java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) > [?:?] > at > java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630) > [?:?] > at > org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) > [tomcat-util.jar:9.0.40] > at java.lang.Thread.run(Thread.java:832) [?:?] > Caused by: oracle.jdbc.OracleDatabaseException: ORA-02291: integrity > constraint (JCOMMOPS_B.PTF_HARDWARE_FK) violated - parent key not found > > > > -----Original Message----- > From: Michael Gentry <blackn...@gmail.com> > Sent: Thursday, November 4, 2021 7:28 PM > To: Cayenne Users <user@cayenne.apache.org> > Subject: Re: Insertion order issue > > CAUTION: This message comes from an external server, do not click on links > or open attachments unless you know the sender and are sure the content is > safe. > > > Hi Anthonin, > > Perhaps put a @SortWeight(2) annotation [1] on your child entity? Also, > you need to configure a different entity sorter: > > // Need WeightedAshwoodEntitySorter for @SortWeight to work. > Module entitySorterModule = (binder) -> > binder.bind(EntitySorter.class).to(WeightedAshwoodEntitySorter.class); > ServerRuntime runtime = > ServerRuntimeBuilder.builder().addModule(myModule).... > > If this doesn't help, please provide a stack track and Cayenne version > information. > > Thanks! > > mrg > > > [1] > > https://cayenne.apache.org/docs/4.0/api/org/apache/cayenne/ashwood/SortWeight.html > > > On Thu, Nov 4, 2021 at 10:38 AM Lize Anthonin (OceanOPS) < > al...@groupcls.com> > wrote: > > > Hi, > > > > I am using Cayenne in a web app (through AgRest, but this is purely > > cayenne related, well I think so) that contains one service through a > > POST method. > > Basically, I submit a JSON body with multiple object in it, pass it > > through the service method defined below, process each object and for > > each ones doing some insert into an Oracle DB. > > @POST > > @Consumes(MediaType.APPLICATION_JSON) > > @Path("getid") > > @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") public > > List<IdResponse> getID(final List<IdInput> inputs) { > > There I loop over this list, process the object > > IdInput and make the necessary insertions } > > > > My issue there is that when I commit the changes, the order of the > > inserts seems to fail randomly, from one request to another. I have > > relationships set in those modifications, and through the logs I can > > see the PK being fetched from the sequences, but then sometimes (most > > of the times) the referencing entity is inserted before the referenced > > entity. And of course the commit fail for violation of parent key. > > > > I've tried to secure as much as possible the context, through > > different > > ways: > > > > * stateless thread context through the provided cayenne filter > > (stateless because the session one would be committed via another > > commit made in another filter, weird, but I send only one request, > > this filter commit should happen prior to the 'service' commit) > > * per method context > > * custom stateless context through a filter that I made myself. > > I thought I got it with he per method context, but it failed after a > while. > > And I tried committing after each processing in the loop, or after the > > loop, but same results. > > > > I'm probably missing something, but I'm not getting why it happen > > sometimes, not always(or never!). A threading issue maybe? But I'm > > processing only one request, so I'm a bit lost. > > Any thoughts? (before I commit after each insertion of entities haha) > > How the order of inserts are defined? Maybe I miss-configured some > > relationships in the modeler, but they come from a reverse engineering > > and look ok... > > > > Many thanks in advance > > Anthonin > > ________________________________ > > > > Ce message et toutes les pi?ces jointes (ci-apr?s le "message") sont > > ?tablis ? l'intention exclusive de ses destinataires et sont > confidentiels. > > Si vous recevez ce message par erreur ou s'il ne vous est pas destin?, > > merci de le d?truire ainsi que toute copie de votre syst?me et d'en > > avertir imm?diatement l'exp?diteur. Toute lecture non autoris?e, toute > > utilisation de ce message qui n'est pas conforme ? sa destination, > > toute diffusion ou toute publication, totale ou partielle, est > > interdite. L'Internet ne permettant pas d'assurer l'int?grit? de ce > > message ?lectronique susceptible d'alt?ration, l'exp?diteur (et ses > > filiales) d?cline(nt) toute responsabilit? au titre de ce message dans > l'hypoth?se o? il aurait ?t? > > modifi? ou falsifi?. > > > > This message and any attachments (the "message") is intended solely > > for the intended recipient(s) and is confidential. If you receive this > > message in error, or are not the intended recipient(s), please delete > > it and any copies from your systems and immediately notify the sender. > > Any unauthorized view, use that does not comply with its purpose, > > dissemination or disclosure, either whole or partial, is prohibited. > > Since the internet cannot guarantee the integrity of this message > > which may not be reliable, the sender (and its subsidiaries) shall not > > be liable for the message if modified or falsified. > > > ________________________________ > > Ce message et toutes les pièces jointes (ci-après le "message") sont > établis à l'intention exclusive de ses destinataires et sont confidentiels. > Si vous recevez ce message par erreur ou s'il ne vous est pas destiné, > merci de le détruire ainsi que toute copie de votre système et d'en avertir > immédiatement l'expéditeur. Toute lecture non autorisée, toute utilisation > de ce message qui n'est pas conforme à sa destination, toute diffusion ou > toute publication, totale ou partielle, est interdite. L'Internet ne > permettant pas d'assurer l'intégrité de ce message électronique susceptible > d'altération, l’expéditeur (et ses filiales) décline(nt) toute > responsabilité au titre de ce message dans l'hypothèse où il aurait été > modifié ou falsifié. > > This message and any attachments (the "message") is intended solely for > the intended recipient(s) and is confidential. If you receive this message > in error, or are not the intended recipient(s), please delete it and any > copies from your systems and immediately notify the sender. Any > unauthorized view, use that does not comply with its purpose, dissemination > or disclosure, either whole or partial, is prohibited. Since the internet > cannot guarantee the integrity of this message which may not be reliable, > the sender (and its subsidiaries) shall not be liable for the message if > modified or falsified. >