I have a system where we are batching up Hibernate objects and logging
them to the database asynchronously. We are inserting a continuous
stream of many objects. The resulting rows are only accessed with SQL
on an infrequent basis from other processes.
I noticed our system getting bogged down logging one of these types of
objects with a mapping similar to:
Code:
<hibernate-mapping default-lazy="false">
<class name="Foo" table="FOO" mutable="false">
<id name="id" column="ID" type="java.lang.Long">
<generator class="native"/>
</id>
<list name="bars" lazy="false" cascade="all-delete-orphan">
<key column="FOO_ID"/>
<index column="POSITION"/>
<one-to-many class="Bar"/>
</list>
<!-- a bunch of properties -->
</class>
<class name="Bar" table="BAR" mutable="false">
<id name="id" column="ID" type="java.lang.Long">
<generator class="native"/>
</id>
<property name="baz" type="int" update="true" insert="true"
column="BAZ"/>
</class>
</hibernate-mapping>
Looking at the Hibernate logs, I see that first see my parent object
Foo inserted, then each Bar object in the child list gets its
properties inserted, then each Bar row is updated with the id of its
parent and position in the list.
Code:
30 11:25:57.515 DEBUG [SQL] insert into FOO (ID) values (?)
30 11:25:57.518 DEBUG [SQL] insert into BAR (BAZ, ID) values (?, ?)
30 11:25:57.518 DEBUG [SQL] insert into BAR (BAZ, ID) values (?, ?)
30 11:25:57.518 DEBUG [SQL] insert into BAR (BAZ, ID) values (?, ?)
30 11:25:57.528 DEBUG [SQL] update BAR set FOO_ID=?, POSITION=? where ID=?
30 11:25:57.528 DEBUG [SQL] update BAR set FOO_ID=?, POSITION=? where ID=?
30 11:25:57.528 DEBUG [SQL] update BAR set FOO_ID=?, POSITION=? where ID=?
I have since discovered that the reason we were getting bogged down
doing these updates was that Postgres 7.4.7 doesn't know that it can
use an int8 index when presented with an int4 literal. My experiments
suggest that this has been fixed in Postgres 8. This will fix the
immediate problem.
Still, I would like to make the Hibernate classes we use in this
fashion to only use INSERT. I have enough problems, the less I can
have the database bogged down doing unnecessary work, the better.
Is there any way to add a child list to the database with no UPDATEs?
It seems like that is just the algorithm you use to persist a graph of
objects, but perhaps there is another way to avoid the UPDATE.