-->
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.  [ 8 posts ] 
Author Message
 Post subject: Bidir. associations with join table and joined-subclass
PostPosted: Fri Apr 14, 2006 9:50 am 
Newbie

Joined: Fri Apr 14, 2006 9:37 am
Posts: 5
Hi, i'm evaluating Hibernate to provide an O/R mapping onto a legacy database.
I followed the examples provided in section 7.5.1 of Hibernate 3.1.x documentation: "Bidirectional associations with join tables". The one-to-one example, with Person and Adddress connected by a bidirectional association mapped on a join table (PersonAddress), works fine. The same for the many-to-one association mapped on a join table.

The problem starts by simply adding a subclass to Address, using the <joined-subclass> strategy. When you call Configuration.buildSessionFactory, an exception is thrown during the evaluation of the added subclass

Code:
org.hibernate.AssertionFailure: Table PersonAddress not found
   at org.hibernate.persister.entity.JoinedSubclassEntityPersister.getTableId(JoinedSubclassEntityPersister.java:444)
   at org.hibernate.persister.entity.JoinedSubclassEntityPersister.<init>(JoinedSubclassEntityPersister.java:225)
   at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:58)
   at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:216)
   at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1176)
   at Test.main(Test.java:8)


Any idea on what causes this behaviour ?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 14, 2006 8:37 pm 
Regular
Regular

Joined: Wed Jul 07, 2004 2:00 pm
Posts: 64
Could you post your mapping documents?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 15, 2006 7:36 am 
Newbie

Joined: Fri Apr 14, 2006 9:37 am
Posts: 5
test/Address.hbm.xml:
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="test.Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress" optional="true" inverse="true">
        <key column="addressId" unique="true"/>
        <many-to-one name="person"
            column="personId"
            not-null="true"
            unique="true"/>
    </join>
  </class>
</hibernate-mapping>


test/Person.hbm.xml
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="test.Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <join table="PersonAddress" optional="true">
        <key column="personId" unique="true"/>
        <many-to-one name="address"
            column="addressId"
            not-null="true"
            unique="true"/>
    </join>
  </class>
</hibernate-mapping>


test/Worker.hbm.xml
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>
  <joined-subclass name="test.Worker" extends="test.Person">
    <key column="WID"/>
    <property name="workType" type="string"/>
  </joined-subclass>
</hibernate-mapping>


I've found two ways for removing the exception I posted above:
- Remove Worker from the hibernate configuration (i.e. returning to a non-hierarchical model, with 2 classes and their join association)
- Remove the <join> association from Address and Person (i.e. preserving the hierarchical model, with 3 classes, but removing the join association)
In other words I can't make <join> and <joined-sublcass> to co-exist.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 15, 2006 7:49 am 
Newbie

Joined: Fri Apr 14, 2006 9:37 am
Posts: 5
Btw, I've found this workaround for mapping my legacy one-to-one and many-to-one associations on join tables in case of hierarchies of joined subclasses:
- Build the Java classes and mapping files as if the associations are MANY-TO-MANY (see section 7.5.3 of Hibernate 3.1.x manual)
Code:
// Address.java
public Set getPersonSet() {
    return personSet;
}
public void setPersonSet(Set personSet) {
    this.personSet = personSet;
}
...
<!-- Address.hbm.xml -->
<set name="personSet" table="MYJOINTABLE">
    <key ..../>
    <many-to-many .../>
</set>



- Adds to the Java classes, but NOT to the mapping files, a pair of suitable setter and getter, implemented using the above many-to-many setter and getter, enforcing the "one" max cardinality.
Code:
// Address.java
public Person getPerson() {
    Set set = getPersonSet();
    if (!set.isEmpty()) {
        return (Person) set.iterator().next();
    } else {
        return null;
    }
}
public void setPerson(Set person) {
    Set set = getPersonSet();
    set.clear();
    if (person != null) {
        set.add(person);
    }
}


In this way the class exposes one-to-one methods, Hibernate does the job of updating the underlying join table, and the getter/setter methods enforces programmatically the cardinality. And all works with hierarchies of classes and with one-to-one or many-to-one associations put at any level of the hierarchy.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 15, 2006 1:30 pm 
Regular
Regular

Joined: Wed Jul 07, 2004 2:00 pm
Posts: 64
From the Hibernate documentation, it looks like the <join> element is not used to do bidirectional relationships with a join table, but to allow properties of a single class to be split among multiple tables. In this case, your problem is that the <join> in Address and <join> in Person are both using the same table for these split properties.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 15, 2006 2:01 pm 
Newbie

Joined: Fri Apr 14, 2006 9:37 am
Posts: 5
According to section 7.5.1 and section 7.5.2 of the Hibernate 3.1.x manual, the <join> element can be used to map as well bidirectional associations. And it works perfectly. Until you introduce a joined subclass in the system.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Apr 15, 2006 4:27 pm 
Regular
Regular

Joined: Wed Jul 07, 2004 2:00 pm
Posts: 64
Well, I finally got around to actually trying this out. Want to hear something funny? The bug has nothing to do with trying to get a many-to-many relationship working with <join>. Here's my mapping:
<?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 default-access="field" package="com.david.model">
<class name="Person" table="person" select-before-update="true" dynamic-update="true">
<id name="id" column="id" type="long">
<generator class="native"/>
</id>
<version name="version" column="version" type="long"/>
<property name="birthDate" column="birth_date" type="date"/>
<property name="firstName" column="first_name" type="string" length="20" not-null="true"/>
<property name="lastName" column="last_name" type="string" length="20" not-null="true"/>
<join table="personDesc" inverse="false" optional="true">
<key column="personId"/>
<property name="hairColor" column="hair_color" type="string" length="10"/>
</join>
</class>
<joined-subclass name="Employee" table="employee" extends="Person">
<key column="personId"/>
<property name="salary" column="salary" type="big_decimal"/>
</joined-subclass>
</hibernate-mapping>

What I am doing is splitting the properties for the base Person - most go in the person table, but the hair color is in the personDesc table. I get the same exception when Hibernate tries to create the session factory - for Employee, it can't find the personDesc table. After a quick run under debug, it turns out that JoinedSubclassEntityPersister examines all properties of the base class and subclass, but expects that all properties (at least, based on the above mapping) are in the person or employee table, and freaks out when it sees that hairColor belongs to the personDesc table.

Looks like you found a real Hibernate bug!


Top
 Profile  
 
 Post subject: Ok, bug found
PostPosted: Tue Apr 25, 2006 7:40 pm 
Newbie

Joined: Tue Apr 25, 2006 7:36 pm
Posts: 1
Ok, keeminor found a bug, DWright confirmed the existence... I'm having the exact same problem... should I use the work around suggested by keeminor or is there any patch I could use?

Thanks a lot for your help :-)


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