-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: collection: duplicate rows in association table
PostPosted: Mon Apr 19, 2004 5:26 pm 
Regular
Regular

Joined: Thu Apr 15, 2004 1:12 pm
Posts: 55
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


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 19, 2004 10:51 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
Can you post the source code for ProductSelection and any of its referenced classes which go into the make up of ProductSelection's equals() and hashCode()?

What happens if you map this association using a bag instead?

This is most likely an issue with the equals() and hasCode() definition. If the bag usage works it is almost definitely an equals()/hashCode() issue.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 20, 2004 1:50 am 
Regular
Regular

Joined: Thu Apr 15, 2004 1:12 pm
Posts: 55
Hi Steve, thanks for your reply!

I mapped the collection as a <bag>, and the duplicate rows went away.

So, I proceeded to implement equals() and hashCode() for the 3 classes that needed it (I used the commons-lang builder package for most of these methods). Tested the methods and convinced myself they were correct.

But I still get the duplicate rows!

Any other guesses as to what the trouble might be?

thanks,
mark


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.