Hi all,
I would like to know if there a definitive answer regarding the issue of (potentially) unnecessary updates following inserts, when using bi-directional associations with indexed collections. Of course when I say "unnecessary" it is from my own point of view, there might be a good reason for this behavior but I do not see it. I have read the entire online doc, the book Hibernate in Action and I've also spent quite a bit of time searching for this on the forums, but to no avail. I did find some related info, but no definitive answer. It might be obvious to some of you, and I apologize if this is actually a rehash of a well-understood issue.
Suppose I have a Parent class and a Child class, and that objects of these classes are linked together using a bidirectional association with an indexed collection. This is the 2nd case described in section 6.3.3 of the documentation:
http://www.hibernate.org/hib_docs/v3/reference/en/html_single#collections-indexedbidirectional. The only difference is that I am using a List instead of a Map as the indexed collection. Please keep in mind that I CANNOT use inverse="true" in this case, as explained in the documentation. Like the doc suggests, I am using the insert="false" update="false" workaround on the child.
Here is the Parent class mapping:
Code:
<class name="Parent" table="parent">
<id name="id" column="id">
<generator class="native"/>
</id>
<list name="children" table="child" cascade="all">
<key column="parent_id" not-null="true"/>
<list-index column="position"/>
<one-to-many class="Child"/>
</list>
</class>
And here's the Child class mapping:
Code:
<class name="Child" table="child">
<id name="id" column="id">
<generator class="native"/>
</id>
<many-to-one name="parent"
column="parent_id"
insert="false"
update="false"
not-null="true"/>
</class>
Now, when I execute this code:
Code:
sf.getCurrentSession().beginTransaction();
Parent parent = new Parent();
Child child = new Child();
child.setParent(parent);
parent.getChildren().add(child);
sf.getCurrentSession().save(parent);
sf.getCurrentSession().getTransaction().commit();
The following SQL statements are issued:
Code:
16:11:55,247 DEBUG SQL:393 -
insert
into
parent
(id)
values
(?)
16:11:55,262 DEBUG LongType:80 - binding '13' to parameter: 1
16:11:55,262 DEBUG SQL:393 -
insert
into
child
(parent_id, position, id)
values
(?, ?, ?)
16:11:55,262 DEBUG LongType:80 - binding '13' to parameter: 1
16:11:55,278 DEBUG IntegerType:80 - binding '0' to parameter: 2
16:11:55,278 DEBUG LongType:80 - binding '14' to parameter: 3
16:11:55,278 DEBUG SQL:393 -
update
child
set
parent_id=?,
position=?
where
id=?
16:11:55,293 DEBUG LongType:80 - binding '13' to parameter: 1
16:11:55,293 DEBUG IntegerType:80 - binding '0' to parameter: 2
16:11:55,293 DEBUG LongType:80 - binding '14' to parameter: 3
As you can see, the last UPDATE is, in theory at least, unnecessary because everything was already properly inserted into the DB after the last INSERT. If I had used a Set instead of a List, mapped with inverse="true", I would not be getting that last UPDATE.
Also I would like to draw your attention to the following sentence in the documentation (at the end of section 6.3.3):
Quote:
TODO: Does this really result in some unnecessary update statements?
Apparently I am not alone wondering about this ;) So then, is there any way to avoid these UPDATE's while still using a bidirectional association with an indexed collection?
Thank you very much,
Mathieu