Hi,
I'm running Hibernate 2.1 w/ MySQL 3.23.
I have a unit test that calls Session.flush() at several points, so that I can peek in at the database and see if the tables look the way I expect them to. I was seeing a bizarre behavior in a collection association table, where I was ending up with duplicate rows! After a bit of hacking around and trying to isolate the problem, I figured out out that the duplicate rows are related to the multiple calls to flush(). My cut-down test case now just creates a collection, adds some items to it, persists the collection, and then calls flush() three times in succession. Sure enough, I get 2 extra, duplicate rows (for a total of three rows), for each row that I expect to see in the table!
The log info shows that on the second and third calls to flush(), Hibernate is trying to delete all the rows, and then re-insert them. So it would appear that the delete is not working for some reason.
Questions:
1) Why
would flush() want to delete all the rows in this situation? Remember, I am calling flush() three times in succession, I'm not touching the collection or anything else in between the calls to flush() (so this isn't a case of
http://www.hibernate.org/116.html#A12).
2) What might be causing the deletes to fail?
3) Why does't Hibernate seem to know they failed?
4) How do I fix this?
Here's my mapping for the class containing the collection:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 1.1//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="SiteProperties"
>
<id
name="id"
column="id"
type="java.lang.Long"
>
<generator class="native">
</generator>
</id>
<set
name="productSelections"
lazy="false"
inverse="false"
cascade="none"
sort="unsorted"
>
<key
column="site_properties_id"
/>
<composite-element
class="ProductSelection"
>
<many-to-one
name="product"
class="Product"
cascade="none"
outer-join="auto"
column="product"
/>
<nested-composite-element
name="price"
class="MonetaryAmount"
>
<property
name="scale"
type="short"
column="scale"
[sharpei:wrinkledog/xeroxbuilder/webbuilder] ml% cat XXX
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 1.1//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="SiteProperties"
>
<id
name="id"
column="id"
type="java.lang.Long"
>
<generator class="native">
</generator>
</id>
<set
name="productSelections"
lazy="false"
inverse="false"
cascade="none"
sort="unsorted"
>
<key
column="site_properties_id"
/>
<composite-element
class="ProductSelection"
>
<many-to-one
name="product"
class="Product"
cascade="none"
outer-join="auto"
column="product"
/>
<nested-composite-element
name="price"
class="MonetaryAmount"
>
<property
name="scale"
type="short"
column="scale"
/>
<property
name="value"
type="long"
column="value"
/>
<property
name="currency"
type="Currency"
column="currency"
/>
</nested-composite-element>
</composite-element>
</set>
<!--
To add non XDoclet property mappings, create a file named
hibernate-properties-SiteProperties.xml
containing the additional properties and place it in your merge dir.
-->
</class>
</hibernate-mapping>
And here is the Hibernate log dumpage for the 2nd call to flush():
Code:
[java] DEBUG - flushing session
[java] DEBUG - Collection dirty: [SiteProperties.productSelections#1]
[java] DEBUG - Flushing entities and processing referenced collections
[java] DEBUG - Collection found: [SiteProperties.productSelections#1], was: [SiteProperties.productSelections#1]
[java] DEBUG - Processing unreferenced collections
[java] DEBUG - Scheduling collection removes/(re)creates/updates
[java] DEBUG - Flushed: 0 insertions, 0 updates, 0 deletions to 4 objects
[java] DEBUG - Flushed: 0 (re)creations, 1 updates, 0 removals to 1 collections
[java] DEBUG - listing entities:
[java] DEBUG - SiteProperties{productSelections=[ProductSelection{product=Product#1, price=MonetaryAmount{value=12300, currency=0, scale=100}}, ProductSelection{product=Product#2, price=MonetaryAmount{value=45600, currency=0, scale=100}}, ProductSelection{product=Product#3, price=MonetaryAmount{value=78900, currency=0, scale=100}}], id=1}
[java] DEBUG - Product{price_CDN=MonetaryAmount{value=0, currency=1, scale=100}, omarId=null, productId=null, price_USD=MonetaryAmount{value=0, currency=0, scale=100}, note=null, name=test product 1, id=1}
[java] DEBUG - Product{price_CDN=MonetaryAmount{value=0, currency=1, scale=100}, omarId=null, productId=null, price_USD=MonetaryAmount{value=0, currency=0, scale=100}, note=null, name=test product 3, id=3}
[java] DEBUG - Product{price_CDN=MonetaryAmount{value=0, currency=1, scale=100}, omarId=null, productId=null, price_USD=MonetaryAmount{value=0, currency=0, scale=100}, note=null, name=test product 2, id=2}
[java] DEBUG - executing flush
[java] DEBUG - Deleting rows of collection: [SiteProperties.productSelections#1]
[java] DEBUG - about to open: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG - delete from productSelections where site_properties_id=? and product=? and scale=? and value=? and currency=?
[java] Hibernate: delete from productSelections where site_properties_id=? and product=? and scale=? and value=? and currency=?
[java] DEBUG - preparing statement
[java] DEBUG - binding '1' to parameter: 1
[java] DEBUG - binding '2' to parameter: 2
[java] DEBUG - binding '100' to parameter: 3
[java] DEBUG - binding '0' to parameter: 4
[java] DEBUG - binding '0' to parameter: 5
[java] DEBUG - Adding to batch
[java] DEBUG - binding '1' to parameter: 1
[java] DEBUG - binding '3' to parameter: 2
[java] DEBUG - binding '100' to parameter: 3
[java] DEBUG - binding '0' to parameter: 4
[java] DEBUG - binding '0' to parameter: 5
[java] DEBUG - Adding to batch
[java] DEBUG - binding '1' to parameter: 1
[java] DEBUG - binding '1' to parameter: 2
[java] DEBUG - binding '100' to parameter: 3
[java] DEBUG - binding '0' to parameter: 4
[java] DEBUG - binding '0' to parameter: 5
[java] DEBUG - Adding to batch
[java] DEBUG - done deleting collection rows: 3 deleted
[java] DEBUG - Updating rows of collection: SiteProperties.productSelections#1
[java] DEBUG - done updating rows: 0 updated
[java] DEBUG - Inserting rows of collection: [SiteProperties.productSelections#1]
[java] DEBUG - Executing batch size: 3
[java] DEBUG - done closing: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG - closing statement
[java] DEBUG - about to open: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG - insert into productSelections (site_properties_id, product, scale, value, currency) values (?, ?, ?, ?, ?)
[java] Hibernate: insert into productSelections (site_properties_id, product, scale, value, currency) values (?, ?, ?, ?, ?)
[java] DEBUG - preparing statement
[java] DEBUG - binding '1' to parameter: 1
[java] DEBUG - binding '1' to parameter: 2
[java] DEBUG - binding '100' to parameter: 3
[java] DEBUG - binding '12300' to parameter: 4
[java] DEBUG - binding '0' to parameter: 5
[java] DEBUG - Adding to batch
[java] DEBUG - binding '1' to parameter: 1
[java] DEBUG - binding '2' to parameter: 2
[java] DEBUG - binding '100' to parameter: 3
[java] DEBUG - binding '45600' to parameter: 4
[java] DEBUG - binding '0' to parameter: 5
[java] DEBUG - Adding to batch
[java] DEBUG - binding '1' to parameter: 1
[java] DEBUG - binding '3' to parameter: 2
[java] DEBUG - binding '100' to parameter: 3
[java] DEBUG - binding '78900' to parameter: 4
[java] DEBUG - binding '0' to parameter: 5
[java] DEBUG - Adding to batch
[java] DEBUG - done inserting rows: 3 inserted
[java] DEBUG - Executing batch size: 3
[java] DEBUG - done closing: 0 open PreparedStatements, 0 open ResultSets
[java] DEBUG - closing statement
[java] DEBUG - post flush
Thanks very much for any help!
mark lundquist