You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@cayenne.apache.org by Mike Kienenberger <mk...@gmail.com> on 2006/08/26 21:58:14 UTC

Intercepting BatchQueries after sql is generated

> On Dec 30, 2005, at 11:27 PM, Mike Kienenberger wrote:
> > I don't quite understand what you're proposing.   How would one get
> > the needed information out of a batch query?

Now that I've looked at the BatchQuery object, this was a naive question :-)
The BatchQuery contains EXACTLY the information I need.  Thanks for
being patient :-)

Furthermore, I don't think I need to set relationships if I'm using
the direct values.   The only question will be how I can get the
foreign keys injected into my Log object relationships without
breaking them.  Probably not insurmountable.

It looks like the best place to intercept the queries is in
DataDomainFlushAction.flush(), right between runQueries() and
postprocess(context).    Since we have access to the DataContext, this
seems like it'd be a reasonable place to call a
DataContextDelegate.queriesDidRun(List queries) method.

So I need to set a user-managed transaction, create a
DataContextDelegate that reparses all of the queries, turning them
into Log objects (or into datarows), let the first commit finish, then
recommit again with the new Log objects and close out the user
transaction.

On 12/31/05, Andrus Adamchik <an...@objectstyle.org> wrote:
>
>
> BatchQuery contain a matrix of values keyed by DbAttribute - this is
> what you need for audit, right? Still need to think how to handle
> deferred generated keys, but if we intercept the query at the right
> moment, they can be already there, solving your other problem as well.
>
> BatchQuery q;
> List dbAttributes = q.getDbAttributes();
> while(q.next()) {
>     for(int i = 0; i < q.size(); i++) {
>        DbAttribute a = (DbAttribute) dbAttributes.get(i);
>        Object value = q.getValue(i);
>
>        // append this data to the audit log
>        // ...
>
>        // note that in UPDATE batches attribute can be either
>        // from 'UpdatedAttributes' or 'QualifierAttributes'
>     }
> }
>
> // reset the batch so that Cayenne could process it again later
> q.reset();
>
>
> > And then add new objects to the commit?   The process of adding
> > more inserts is
> > probably the two-stage commit that you're talking about.
>
> Yes. If possible you can simply append the audit log to your own
> InsertBatchQuery (maybe attaching it to the DataContext via
> "setUserProperty"). If not, you can create unregistered DataObjects
> (you won't have any relationships in them, right?), register them in
> DataContext after the first commit stage is done, and then commit again.
>
>
> > Sounds interesting, but I need something that works in the present,
> > and it
> > sounds like this might require a lot of work before it's ready for
> > use.
>
> This may not be as bad, but it will certainly require some attention.
> I'll log a Jira improvement task.
>
>
> > What I'm doing now works.   It isn't clean, but it works.
>
> I agree and realize that you need a solution now. And I think you
> don't need a patch to use your approach. Subclassing would be enough.
> The trick is to put your subclass in org.objectstyle.cayenne.access
> package (inside your application source tree of course). The fields
> you need to access are not private, they are just not public, so by
> doing that you'll get full access to these methods:
>
> package org.objectstyle.cayenne.access;
>
> public class MyDataContext extends DataContext {
>      ...
>
>      public List newFlattenedObjects()
>      {
>          // maybe wrap in new ArrayList() first....
>          return getObjectStore().getFlattenedInserts();
>      }
>      public List deletedFlattenedObjects()
>      {
>          // maybe wrap in new ArrayList() first....
>          return getObjectStore().getFlattenedDeletes();
>      }
>
>      ...
> }
>
>