Re: isIteratedResult and SPs

From: Andrus Adamchik (andru..bjectstyle.org)
Date: Mon Apr 10 2006 - 05:38:39 EDT

  • Next message: Bill Dudney: "Re: CLA's for Cayenne?"

    Cris,

    you lost me here...

    If you have a user transaction manually bound to thread, you'd still
    have to commit a DataContext via "commitChanges()" which basically
    does a flush without commit ... and then commit a transaction that
    does a DB commit (and calls the delegate method).

    But I guess the whole point of the delegate is to avoid manual
    transaction handling. So I am more interested whether Cayenne-
    initiated transactions work. More specifically if you replace this
    part of "willCommit" of the delegate:

    >>> transaction.performQueries(dataContext,
    >>> Collections.singleton(updateQuery), new DefaultOperationObserver() {
    >>>
    >>> ..verride
    >>> public boolean isIteratedResult() {
    >>> return true;
    >>> }
    >>>
    >>> });

    with this line:

    dataContext.performGenericQuery(query);

    That's what I meant by "running directly via DataContext"... implying
    "running directly via DataContext inside 'willCommit' method". Does
    it work?

    Andris

    On Apr 10, 2006, at 1:49 AM, Cris Daniluk wrote:
    > I can run the ProcedureQuery directly via the context, but it is a
    > committing operation. If I bind a Transaction to the thread, I can
    > get the
    > ProcedureQuery to run in the TransactionDelegate, but only if I
    > commit the
    > Transaction, and not if I commit the DataContext.
    >
    > Basically, if I make some objects dirty, then bind a Transaction, then
    > commit the DataContext, the Transaction is not committed. If I
    > commit the
    > Transaction instead in that scenario, the objects are not flushed.
    > This
    > behavior seemed a little off to me and I was planning on testing in
    > the beta
    > to see if it still worked that way.
    >
    > Meanwhile, I have put in place a fairly ugly hack. I have a
    > LocalTransactionDelegate bound to the DataDomain which looks in a
    > ThreadLocal Context I have (non-Cayenne) for a TransactionDelegate and
    > executes it. This way, I can essentially have a ThreadLocal
    > TransactionDelegate instead of the DataDomain-specific
    > TransactionDelegate.
    > This allows me to much more cleanly inject stored procedures into the
    > transaction, and it properly puts the stored procedure execution at
    > the end
    > of the flushed write operations. However, it still doesn't work
    > without
    > isIteratedResultSet :)
    >
    > The good news is if I bind a Transaction and then execute the query
    > inside
    > of that, it does not execute the commit, which is the correct
    > behavior. I
    > just have to retest in the beta to see if the other annoying side
    > effects
    > (not flushing the writes first) is fixed. It seems to me like there
    > ought to
    > be some sort of feature buried in here... something like a
    > PostFlushProcedureQuery. I think the current behavior is correct in
    > most
    > cases, but for this particular case, it is a problem.
    >
    > Oh, and the "LocalTransactionDelegate" is kind of handy too. We
    > could easily
    > add a TransactionDelegate property to the DataContext that was
    > deferred to
    > if the user sets the DataDomain to "LocalTransactionDelegate". I
    > see a lot
    > of potential applications for that.
    >
    > Cris
    >
    > On 4/8/06, Andrus Adamchik <andru..bjectstyle.org> wrote:
    >>
    >> Cris,
    >>
    >> Is this still a problem? Transaction.performQueries(..) is deprecated
    >> and indeed attempts to commit internally. Can you run the
    >> ProcedureQuery directly via DataContext? It should pick up the same
    >> thread transaction.
    >>
    >> Andrus
    >>
    >>
    >>
    >> On Feb 28, 2006, at 10:53 PM, Cris Daniluk wrote:
    >>
    >>> 2 weeks later :)
    >>>
    >>> My delegate invokes:
    >>>
    >>> ProcedureQuery updateQuery = (ProcedureQuery)
    >>> dataContext.getEntityResolver().getQuery("MergeDocumentCopy");
    >>> updateQuery.addParameter("documentID", glinID);
    >>> updateQuery.addParameter("userID",
    >>> SessionContext.getSessionContext().getSecurityPrincipal().getUserId
    >>> ());
    >>>
    >>> transaction.performQueries(dataContext,
    >>> Collections.singleton(updateQuery), new DefaultOperationObserver() {
    >>>
    >>> ..verride
    >>> public boolean isIteratedResult() {
    >>> return true;
    >>> }
    >>>
    >>> });
    >>>
    >>> Note that I am invoking performQueries on the willCommit
    >>> (Transaction),
    >>> and not on the context itself. In fact, I'm relatively convinced
    >>> that
    >>> if I were to skip the TransactionDelegate altogether and simply pass
    >>> this modified OperationObserver to the
    >>> dataContext.performQueries, it
    >>> would do precisely the right thing.
    >>>
    >>> Perhaps this could be tweaked into cool functionality?
    >>>
    >>> On 2/14/06, Andrus Adamchik <andru..bjectstyle.org> wrote:
    >>>>
    >>>> On Feb 14, 2006, at 6:47 PM, Cris Daniluk wrote:
    >>>>
    >>>>>> There are two "official" ways to avoid commit - external
    >>>>>> transactions
    >>>>>> and user-managed transactions. Can you explain why commit is
    >>>>>> undesirable. Is this a standalone ProcedureQuery, or is this
    >>>>>> something you are doing from TransactionDelegate?
    >>>>>>
    >>>>> Running it from a TransactionDelegate. It is happening after a
    >>>>> ton of
    >>>>> insert/updates, but before the overall commit. I would be okay
    >>>>> with it
    >>>>> committing, except that after it commits, the DataContext tries to
    >>>>> again and blows up.
    >>>>
    >>>> That's very strange. Double commit shouldn't happen. Could you post
    >>>> the code from the delegate that executes a query?
    >>>>
    >>>> Andrus
    >>>>
    >>>
    >>
    >>



    This archive was generated by hypermail 2.0.0 : Mon Apr 10 2006 - 05:39:06 EDT