Keep in mind the difference between a flush and a commit in hibernate.
A flush executes all the queued sql against the database without
committing the transaction. Hibernate does this whenever it has changes
that needed to be sent to the database before a query is run.
Otherwise, it defers the flush until just before the commit. Unless
you're using deferred constraints in oracle, constraint violations and
other db-related exceptions will be raised during the flush, not the commit.
What I'd really like to do is configure something in hivemind that would
run just before tapestry commits the response. Then I could call
session.flush() there to force the exception before the response is
committed. I just don't know how I can accomplish this.
-Steve
Michael Sims wrote:
Steve Shucker wrote:
I just realized I had a bug relating to this yesterday and I could
use a little help solving it. I think the solution is to force the
hibernate session to flush before the response is committed, but I'm
not sure how/where to inject that call into tapestry. If I knew
where to make tapestry call my code, getting hibernate to flush is
easy.
If I need to commit or rollback the transaction in a listener method (or
elsewhere),
I inject a thread-bound transaction manager service into my pages. The
transaction
manager has the request-wide session injected into it, and I call methods on the
manager to commit, rollback, etc. I got this idea from Tapestry 5's
tapestry-hibernate project:
http://tinyurl.com/3b3dok
In my implementation, I have split out the ThreadCleanupListener
responsibilities
into another object, but the rest is pretty much the same.
Does this help at all?
In general, I think we should either use an open session in view or
DAO approach, not a hybrid. The point of open session in view is that
developers don't have to worry about transactional contexts,
reenlistment and stuff like that. If you're throwing those gains away
with separate request/response or listener/other transactions, you're
better off letting DAOs manage transactions and getting the benefits
of their narrower scope and cleaner definition of where transactions
start
and stop.
The issue with that, in my case anyway, is that I'm using a SqueezeAdaptor to
transparently squeeze a Hibernate persisted object into class + id, and then
unsqueeze to the full entity on the next request. I do this for client
persistence
and direct link parameters, etc., to keep my objects from being serialized into
the
query string. My SqueezeAdaptor has to have an active session and transaction,
and
this occurs before any listener methods are called. I could have the
SqueezeAdaptor, or anything else that needs to use Hibernate, start and finish
their
own transactions via DAO calls, but this would result in a high number of
transactions per request, so I don't think that would be worth anything.
Worse still, if any of those transactions results in an error, you are supposed
to
close the Session, which detaches all persistent objects and makes it
impossible to
access lazily-initialized properties.
Even if spring says it's ok to start a new transaction in a session
where the previous transaction was rolled back, I think it's a bad
idea. I use open session in view, which is one transaction per
session
in its entire lifetime.
Yes, but what about my scenario with the CRUD application? An administrator
tries
to persist a new user, and there is a primary key violation, but using open
session
in view, you don't know this until the response has already been rendered, and
by
then it's too late to present an error. So, how do you handle this without
comitting the transaction early, before the response has been rendered?
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]