You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cayenne.apache.org by Andrus Adamchik <an...@objectstyle.org> on 2006/04/08 11:30:14 UTC

Re: isIteratedResult and SPs

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() {
>
>             @Override
>             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 <an...@objectstyle.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
>>
>


One more way to customize/intercept Cayenne stack

Posted by Andrus Adamchik <an...@objectstyle.org>.
I think this type of stack customization is very promising:

http://objectstyle.org/confluence/display/CAY/2006/04/11/

DataChannel abstraction is at the core of nested DataContexts feature  
and also Cayenne Web Service. I hope it will become a user  
customization option rather sooner than later.

Andrus



Re: isIteratedResult and SPs

Posted by Cris Daniluk <cr...@gmail.com>.
>
>
> 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).


Yes. Sorry, my complicated explanation was just to walk you through the
process of getting to where I'm at right now. In 1.2M12, when I had a bound
transaction, and called DataContext.commitChanges(), it was commiting that
bound transaction. That's the short version of my story :)

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() {
> >>>
> >>>             @Override
> >>>             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?


Sorry, I thought you meant if I run it from the dataContext outside of the
delegate, which does not appear to work. I will try this way inside the
delegate.

Cris

Re: isIteratedResult and SPs

Posted by Andrus Adamchik <an...@objectstyle.org>.
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() {
>>>
>>>             @Override
>>>             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 <an...@objectstyle.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() {
>>>
>>>             @Override
>>>             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 <an...@objectstyle.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
>>>>
>>>
>>
>>


Re: isIteratedResult and SPs

Posted by Cris Daniluk <cr...@gmail.com>.
Well, the whole stored procedure issue is still a little weird for me.

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 <an...@objectstyle.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() {
> >
> >             @Override
> >             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 <an...@objectstyle.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
> >>
> >
>
>