-->
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.  [ 2 posts ] 
Author Message
 Post subject: many-to-many unidirec. association with multiple fetches pro
PostPosted: Mon Oct 15, 2007 7:40 am 
Newbie

Joined: Wed Sep 12, 2007 6:58 pm
Posts: 2
Hi All,

I have a problem with Hibernate. I spent several weeks trying to figure out what the problem is including browsing through this forum. I have a many-to-many unidirectional association between an entity A and B. So A holds several instances of B in a set, but B has no reference to A. In the relational schema a defined a mapping table BtoAMap for the mapping. Now within a single session I have multiple queries which return the same object of Type A. After each query I map an object of type B to the retrieved object of type A by inserting it into the Bs set of A. So in the end the single object of type A should contain the two Bs in its B set. This works fine. Unfortunately sometimes additional Bs get mapped to the A as well, without me triggering a corresponding action. In the Java layer the mapping from Bs to As has been done correctly but it does not get written into the database correctly. And whether the error happens or not depends on what data is already in the mapping table. This is a very strange error and I think I did something wrong, but I am having troubles figuring out what exactly. If anyone can point me to the right direction, I would be more than happy. I added some code below.

Many Thanks


Hibernate version:
3.1.2

Mapping document for A:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="A" table="A" catalog="s">
        <id name="identifier" type="java.lang.String">
            <column name="identifier"/>
            <generator class="assigned"/>
        </id>
    <set name="B" inverse="false" table="BtoAMap" lazy="false">
            <key>
                <column name="AIdentifier" not-null="true"/>
            </key>
            <many-to-many class="B">
                <column name="BIdentifier" not-null="true"/>
            </many-to-many>
        </set>
    </class>
</hibernate-mapping>


Java Code for A
Code:
public class A extends PersistentObject {
   private static final long serialVersionUID = -1589544330614217874L;
   private Set<B> Bs = new HashSet<B>(0);

   /**
    * Constructs an <code>A</code> object.
    */
   public A() {
   }

   /**
    * Constructs an <code>A</code> object with the specified data.
    *
    * @param identifier   the identifier
    * @param Bs   the Bs
    */
   public A
   (
      String identifier,
      Set<B> Bs
   ) {
      setIdentifier(identifier);
      this.Bs = Bs;
   }


   /**
    * Gets the Bs.
    *
    * @return   the Bs
    */
   public Set<B> getBs() {
      return this.Bs;
   }

   /**
    * Sets the Bs.
    *
    * @param Bs   the Bs
    */
   public void setBs(Set<B> Bs) {
      this.Bs = Bs;
   }
}


Mapping document for B:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="B" table="B" catalog="scviz">
        <id name="identifier" type="java.lang.String">
            <column name="identifier"/>
            <generator class="assigned"/>
        </id>
        <property name="description" type="string">
            <column name="description" not-null="true"/>
        </property>
    </class>
</hibernate-mapping>


Java Code for B
Code:
public class B extends PersistentObject {
   private static final long serialVersionUID = 5642250875210836705L;
   private String description;

   /**
    * Constructs an <code>B</code> object.
    */
   public B() {
   }

   /**
    * Constructs an <code>B</code> object with the specified data.
    *
    * @param description   the description
    */
   public B(String description) {
      this.description = description;
   }
   
   /**
    * Constructs an <code>B</code> object with the specified data.
    *
    * @param identifier   the identifier
    * @param description   the description
    */
   public B(String identifier, String description) {
      setIdentifier(identifier);
      this.description = description;
   }

   /**
    * Gets the description.
    *
    * @return    the description
    */
   public String getDescription() {
      return this.description;
   }

   /**
    * Sets the description.
    *
    * @param description   the description
    */
   public void setDescription(String description) {
      this.description = description;
   }
}


Java Code for PersistentObject
Code:
import java.util.UUID;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

/**
* Super class for all persistent objects, providing identification management and common functionality.
*/
public abstract class PersistentObject implements java.io.Serializable {
   private String identifier = UUID.randomUUID().toString();

   public String getIdentifier() {
      return identifier;
   }
   
   protected void setIdentifier(String identifier) {
      this.identifier = identifier;
   }

   public int hashCode() {
      return new HashCodeBuilder()
         .append(identifier)
         .toHashCode();
   }

   public boolean equals(Object obj) {
      if (obj instanceof PersistentObject == false) {
         return false;
      }
      if (this == obj) {
         return true;
      }
      if (identifier == null) {
         return false;
      }
      
      PersistentObject other = (PersistentObject) obj;
      return new EqualsBuilder()
               .append(identifier, other.identifier)
               .isEquals();
   }

   public String toString() {
      return new ToStringBuilder(this)
               .append("identifier", identifier)
               .toString();
   }
}


Code between sessionFactory.openSession() and session.close():
I used Spring's HibernateTemplate with AOP transaction demarcation. But abstractly the code is like this:

b1 = getHibernateTemplate().find(...);
b2 = getHibernateTemplate().find(...);

queryResultA = getHibernateTemplate().findByNamedParam(...);
iterator = queryResultA.iterator();
while (iterator.hasNext()) {
a = iterator.next();
a.getBs.add(b1);
}

queryResultB = getHibernateTemplate().findByNamedParam(...);
/** the same object as before can be returned by the different query **/
iterator = queryResultB.iterator();
while (iterator.hasNext()) {
a = iterator.next();
a.getBs.add(b2);
}

Full stack trace of any exception that occurs:
No exception occurs.

Name and version of the database you are using:
MySQL 5.0.38-Debian_1-log

The generated SQL (show_sql=true):
There are the SQL insert statements for the mapping table between A and B. Unfortunately someitmes additional ones get created.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 16, 2007 10:59 am 
Newbie

Joined: Wed Sep 12, 2007 6:58 pm
Posts: 2
maybe as a start a general question: is it possible to retrieve the same object twice through two different queries and modify the object once a result of the first query and then as a result of the second query?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.