Konstantin's idea of using the domain object itself as an edit buffer is exactly what I'm saying often leads to trouble. It *can* work -- it just ends up being unnecessarily complicated in most cases.

However, I agree with him that this is *really* not a bug in Hibernate. The Hibernate team does need to have a day of serious self- reckoning about how they handle object identity (JDO got that part right, Hibernate fudged it) -- however, the particular problem you're talking about is intended and correct behavior, because:

(1) you have complete control in the mapping file over how IDs are assigned, and can override that behavior with custom assignment if you want to (as I often do -- I like IDs assigned up front, and never use them as an "is persisted" indicator); and

(2) what you're really worrying about is not actually IDs per se, but the fact that Hibernate does not somehow make your objects transactional and roll them back. **That is not Hibernate's job.** Again, every persistent object in the VM must eventually be persisted or discarded; there is no going back. Rollback is for the database, not your objects!

Cheers,

Paul

P.S. Yes, Konstantin, I guess I am a little too hard on Struts. It was really the lack of squeezers I'm thinking of -- the need to manually stuff/unstuff objects every time they go to and from the client. That creates a lot of grunt work.


On May 3, 2006, at 10:05 AM, James Carman wrote:

Well, I would consider it a bug.  This doesn't just happen on
saveOrUpdate().  And, you don't have to flush the session to get it to
happen either.  Check out the main method on this class:

http://www.carmanconsulting.com/svn/public/tapernate/trunk/src/test/ com/carm
anconsulting/tapernate/util/SessionFactoryFactory.java

It prints out "The id is 1."

-----Original Message-----
From: Konstantin Ignatyev [mailto:[EMAIL PROTECTED]
Sent: Wednesday, May 03, 2006 10:56 AM
To: Tapestry users
Subject: RE: Insert/Update pages and Hibernate

Do not think this is a 'bug'. SaveOrUpdate is a 'convenience' feature and if different strategy is necessary then it can be implemented /easily/ in the
application DAO layer.

Although I personally never needed that, saveOrUpdate magic combined with
'assigned' identifiers work quite well for me.

James Carman <[EMAIL PROTECTED]> wrote: That doesn't avoid the
problem where the id can be set, but the row isn't
actually written to the database. The next time a request comes in, that
object will have its id property set and Hibernate will think it's a
persistent object (when you go to merge), when it really is not. This is quite a nasty bug (it's a bug IMHO) in Hibernate. I wouldn't think that it should write the id property values until after the transaction is really complete. But, I haven't really thought through all of the scenarios as I'm sure they did. Has anyone filed a Jira issue with the Hibernate folks about
this to get some clarification?


-----Original Message-----
From: Konstantin Ignatyev [mailto:[EMAIL PROTECTED]
Sent: Wednesday, May 03, 2006 10:45 AM
To: Tapestry users
Subject: RE: Insert/Update pages and Hibernate

Object itself could be such a buffer (or rather working copy of an object) and later it can be merged with Hibernate session /session.merge () / when
necessary

For the comparison fairness I simply pointed to the fact that Struts does not require all the object fieds to be duplicated in ActionForm as people
often do.

James Carman  wrote: This is exactly what
they're trying to avoid, putting "business objects"
into their page logic. The problem with that, as pointed out earlier, is that it can leave your business objects in an invalid state (they have an identifier assigned to them, but the record isn't actually in the database). So, they're trying to come up with a "buffer" to avoid such a situation.

-----Original Message-----
From: Konstantin Iignatyev [mailto:[EMAIL PROTECTED]
Sent: Wednesday, May 03, 2006 1:38 AM
To: Tapestry users
Subject: Re: Insert/Update pages and Hibernate

FYI: there is no need to 'maintain' ActionForm in  Struts unless you
need to, this is the common mistake.
Business object can be placed in the ActionForm as one field and its
properties accessed and set in OGNL like fashion
via BeanUtils.
http://sandbox.sourcelabs.com/kosta/sashstarter-2.0/docs/ presentation/html/i
mg19.html
http://sandbox.sourcelabs.com/kosta/sashstarter-2.0/docs/ presentation/html/i
mg20.html
http://sandbox.sourcelabs.com/kosta/sashstarter-2.0/docs/ presentation/html/i
mg21.html

It is even easier with Struts' "nested" taglib

Jim Steinberger wrote:
Paul, thanks a lot for your insight; I'm finding it very very helpful.

The only thing I'm really not excited about with this approach is the number of times my domain-properties are going to be repeated throughout
my page classes and/or value-objects.
  After struggling to maintain Struts ActionForms in the face of
domain-changes, seeing how HTML forms can be tied directly to
domain-objects via OGNL in Tapestry was a big selling point behind
getting me to switch.

I'm just pouting, though -- I appreciate the necessity of a data- buffer at the UI level, particularly when dealing with a persistence mechanism
that can potentially leave objects in an indeterminate state.


Thanks again,
Jim


-----Original Message-----
From: Paul Cantrell [mailto:[EMAIL PROTECTED]
Sent: Tuesday, May 02, 2006 10:09 PM
To: Tapestry users
Subject: Re: Insert/Update pages and Hibernate

Jim --

My suggestion would be to keep all the user-entered values around in
an object that's not the manufacturer, but is solely a value object
that is very specific to this particular UI. In most cases, this is
the page class itself:

class CreateEditManufacturer extends BasePage {
     public abstract get/setName();
     public abstract get/setFlavor();
     public abstract get/setBossesFavoriteMarxBrother();
     ...etc...

     public IPage saveManufacturer() {
       try {
         getManufacturer().setName(getName());
         getManufacturer().setBossesFavoriteMarxBrother
(getBossesFavoriteMarxBrother());
 ...etc...
         getManufacturerService().createManufacturer();
       } catch (Exception e) {
setError("Could not create Manufacturer: " + e.getMessage ());
         return this;
       }
     }
}

But perhaps you have a multi-page process or something, where it
becomes simpler to build up the user's responses in a _value object_:

class CreateEditManufacturer extends BasePage {
     @Persist("server")
     public abstract ManufacturerEntryForm get/
setManufacturerEntryForm();

     public IPage saveManufacturer() {
       try {
 values = getManufacturerValues();
         getManufacturer().setName(values.getName());
         getManufacturer().setBossesFavoriteMarxBrother
(values.getBossesFavoriteMarxBrother());
 ...etc...
         getManufacturerService().createManufacturer();
       } catch (Exception e) {
setError("Could not create Manufacturer: " + e.getMessage ());
         return this;
       }
     }
}

class ManufacturerEntryForm implements Serializable { // *not*
persistable!
     ...
}

Either way, the point is that you keep the user's input in a value
object of some kind, page or otherwise, that is -- this is the key --
modeled after the user interface, *not* after the domain object. The
value object is a transcription of what the user entered.

Only when you're ready to do something committable do you apply
changes from the UI to the domain. So you're not cloning the domain
object; you're just not eagerly applying changes to the domain at
each step.

This is not an "always the right answer" practice; it's just a
"usually works best" practice.

But yes, in any case, you're quite right: Hibernate doesn't do any
kind of in-memory rollback on your objects! No matter what approach
you take, you *cannot* manipulate a domain object unless you're
prepared to either (1) commit it or (2) discard it.

Cheers,

Paul

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: tapestry-user- [EMAIL PROTECTED]





--
Thanks,

Konstantin Ignatyev

http://www.kgionline.com





PS: If this is a typical day on planet earth, humans will add fifteen
million tons of carbon to the atmosphere, destroy 115 square miles of
tropical rainforest, create seventy-two miles of desert, eliminate between forty to one hundred species, erode seventy-one million tons of topsoil, add 2.700 tons of CFCs to the stratosphere, and increase their population by
263.000

Bowers, C.A.  The Culture of Denial:
Why the Environmental Movement Needs a Strategy for Reforming Universities
and Public Schools.
New York:  State University of New York Press, 1997: (4) (5) (p.206)


---------------------------------------------------------------------
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]





---------------------------------------------------------------------
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]



_________________________________________________________________
Piano music podcast: http://inthehands.com
Other interesting stuff: http://innig.net



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to