-->
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.  [ 1 post ] 
Author Message
 Post subject: ClassCastException loading union-subclass collection
PostPosted: Thu Apr 19, 2007 11:40 am 
Newbie

Joined: Thu Apr 19, 2007 10:38 am
Posts: 11
Hi to all.
I made this test using the base class org.hibernate.test.TestCase which is bundled in every hibernate source distribution.
Can someone give me a comment about it?
The object model is very simple: a superclass A and two subclasses, B and C. B has a list of C's and C has a reference to B.
The hierarchy is mapped using union-subclass, the list of C's in B is mapped as a one-to-many bidirectional association.
The test creates one instance of B with four C's in the list and saves it in one session. In another session, it loads B and tries to get the first C in the list, and surprisingly a ClassCastException is thrown. This is because the list has the same instance of B four times instead of having thouse four instances of C!
When the property
Code:
<property name="description" type="string" column="DESCRIPTION" />

is added in the mapping of C, *before* the many-to-one tag, the test succeeds!

After debugging both the succeeding and the failing cases, I think this has to do with the generation of aliases that are returned by OneToManyLoader in CollectionAliases[] getCollectionAliases().

Hibernate: 3.2.0.ga (2006.10.16)
Database: Oracle 10g
jdk/jre: jdk1.5.0_08

Test case

Code:
package org.myself.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.test.TestCase;

public class UnionSubclassCollectionTestCase extends TestCase {

   public UnionSubclassCollectionTestCase(String name) {
      super(name);
   }

   @Override
   protected String[] getMappings() {
      return new String[]{"A.hbm.xml", "B.hbm.xml", "C.hbm.xml"};
   }
   @Override
   protected String getBaseForMappings() {
      return "org/myself/test/";
   }

   @Override
   protected boolean recreateSchema() {
      return true;
   }

   public void test() {
      B b = new B();
      b.setName("b");
      b.setAge(1l);

      C c1 = new C();
      c1.setName("c1");
      c1.setDescription("c 1");

      C c2 = new C();
      c2.setName("c2");
      c2.setDescription("c 2");

      C c3 = new C();
      c3.setName("c3");
      c3.setDescription("c 3");

      C c4 = new C();
      c4.setName("c4");
      c4.setDescription("c 4");

      b.getCs().add(c1);
      b.getCs().add(c2);
      b.getCs().add(c3);
      b.getCs().add(c4);

      Session s = this.openSession();
      Transaction tx = s.beginTransaction();
      s.save(b);
      Long bId = b.getOid();
      tx.commit();
      s.close();

      s = this.openSession();
      b = (B) s.load(B.class, bId);
      assertEquals(4, b.getCs().size());
      try {
         C newC = b.getCs().get(0);
      } catch (ClassCastException e) {
         fail("The elements in the list b.getCs() must be of type "
               + C.class);
      }
      s.close();
   }
}


Class A mapping

Code:
<?xml version="1.0" encoding="WINDOWS-1251"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
   <class name="org.myself.test.A" abstract="true">

      <id name="oid" column="ID_CLASSA" type="long"
         unsaved-value="0">
         <generator class="native" />
      </id>
      <version name="version" column="VERSION" />

      <property name="name" type="string" column="NAME"
         not-null="true" />
   </class>
</hibernate-mapping>



Class B mapping

Code:
<?xml version="1.0" encoding="WINDOWS-1251"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
   <union-subclass name="org.myself.test.B" extends="org.myself.test.A"
      table="TEST_CLASSB">
      <list name="cs" inverse="false" lazy="true" cascade="all">
         <key column="ID_B" />
         <list-index column="IDX" />
         <one-to-many class="org.myself.test.C" />
      </list>
      <property name="age" type="long" column="AGE" />
   </union-subclass>
</hibernate-mapping>


Class C mapping

Code:
<?xml version="1.0" encoding="WINDOWS-1251"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
   <union-subclass name="org.myself.test.C" extends="org.myself.test.A"
      table="TEST_CLASSC">
      <property name="description" type="string" column="DESCRIPTION" />
      <many-to-one name="b" column="ID_B" cascade="save-update"
         lazy="proxy" />
   </union-subclass>
</hibernate-mapping>


Class A

Code:
package org.myself.test;

public abstract class A {
   private Long oid;

   private int version;

   private String name;

   public A() {
      super();
   }

   public Long getOid() {
      return oid;
   }

   public void setOid(Long oid) {
      this.oid = oid;
   }

   public int getVersion() {
      return version;
   }

   public void setVersion(int version) {
      this.version = version;
   }

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }
}


Class B

Code:
package org.myself.test;

import java.util.ArrayList;
import java.util.List;

public class B extends A {
   private long age;

   private List<C> cs;

   public B() {
      super();
   }

   public long getAge() {
      return age;
   }

   public void setAge(long age) {
      this.age = age;
   }

   public List<C> getCs() {
      if (cs == null) {
         cs = new ArrayList<C>();
      }
      return cs;
   }

   public void setCs(List<C> cs) {
      this.cs = cs;
   }

}


Class C

Code:
package org.myself.test;

public class C extends A {
   private String description;

   private B b;

   public C() {
      super();
   }

   public String getDescription() {
      return description;
   }

   public void setDescription(String description) {
      this.description = description;
   }

   public B getB() {
      return b;
   }

   public void setB(B b) {
      this.b = b;
   }

}


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

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.