]
Gail Badner commented on HHH-3102:
----------------------------------
This is expected behavior. Calling Session.saveOrUpdate( entity ) on an entity already
associated with the session does nothing.
Cascading ManyToOne collections do not eagerly set identifiers on
saveOrUpdate()
--------------------------------------------------------------------------------
Key: HHH-3102
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3102
Project: Hibernate Core
Issue Type: Bug
Components: core
Affects Versions: 3.2.4.sp1
Reporter: Paul Cowan
Priority: Minor
Attachments: HibernateKeyPoolTest.java
Hi all,
Not 100% sure if you'd call this a 'bug' as I'm not sure if the correct
behaviour is actually specified anywhere. It's certainly oddly inconsistent though.
Please find attached a standalone test case (requires HSQLDB on the classpath; amend
setUp() if you need to use something else) which models a parent-child mapping between
'Mouth' (1) and 'Teeth' (many). The Mouth -> Teeth relationship is
bidirectional, with CascadeType.ALL on the single-valued end. Both Mouth and Tooth use a
@GenericGenerator, which simply allocates integers from a static keypool.
A mouth with one tooth is created, saveOrUpdate()d, session is flushed, a new tooth is
added, mouth is saveOrUpdate()d again, and session is again flushed. The debug output is
as follows:
*** After creation
Mouth (id=null) has teeth [canine(id=null)]
*** Save
Mouth (id=1) has teeth [canine(id=2)]
*** Flush
Hibernate: insert into Mouth (id) values (?)
Hibernate: insert into Tooth (mouthId, name, id) values (?, ?, ?)
Mouth (id=1) has teeth [canine(id=2)]
*** Add new
Mouth (id=1) has teeth [canine(id=2), molar(id=null)]
*** Save again
Mouth (id=1) has teeth [canine(id=2), molar(id=null)]
*** Flush again
Hibernate: insert into Tooth (mouthId, name, id) values (?, ?, ?)
Mouth (id=1) has teeth [canine(id=2), molar(id=3)]
As you can see, when initially created the IDs for the mouth and tooth are both null
(obviously correct). The saveOrUpdate() on the Mouth object then generates identifier
values, even though no DB write has been done yet (the .flush()). So far, so good.
However, when a NEW transient Tooth instance ("molar") is added to the Mouth,
and saveOrUpdate() is called once more, the id generator is not invoked, UNTIL such time
as the session is flushed.
While I guess it's fine for an object in the 'persistent' state not to
actually have an identifier until flush-time (e.g. when using DB-side IDENTITY-type
generation), it just seems inconsistent that with a @GenericGenerator the behaviour would
vary depending on whether the PARENT object was already persistent or not.
There are some obvious workarounds (e.g. flush the session upon saving, or save the child
entity first independently) but I thought I'd clarify if this behaviour is by design
or not and suggest that this be made consistent.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: