I'm having a bit of trouble with getting a mapping to work properly. I have three classes TemplateNode, ProductBranch, and IndexLeaf. TemplateNode is abstract. ProductBranch and IndexLeaf are both concrete subclasses of TemplateNode. ProductBranch holds a list of TemplateNodes which can be either ProductBranch or IndexLeaf instances. When I walk the tree and save the nodes Hibernate puts them into the database correctly with the discriminator values set correctly. However, when I pull the root node out of the database and try to walk the tree again I get a ClassCastException. It seems that no matter what the object's discriminator value was set to it always pulls back a TemplateNode not one of the subclasses. Why am I getting back an instance of an abstract class and not the concrete subclass that was saved?
Code:
<class name="com.activeindexing.advisor.product.template.TemplateNode" table="product_template_node" discriminator-value="0">
<id name="id" column="id" type="long" unsaved-value="0">
<generator class="identity"/>
</id>
<discriminator column="type" type="integer"/>
<property name="productName" column="product_name" type="string"/>
<many-to-one name="parent" column="parent_node_id" class="com.activeindexing.advisor.product.template.TemplateNode"/>
<many-to-one name="productPath" column="product_path_id" class="com.activeindexing.advisor.product.ProductPath"/>
<subclass name="com.activeindexing.advisor.product.template.IndexLeaf" proxy="com.activeindexing.advisor.product.template.IndexLeaf" discriminator-value="1">
<many-to-one name="indexIdentifier" column="index_identifier_id" class="com.activeindexing.advisor.market.index.IndexIdentifier" cascade="all"/>
</subclass>
<subclass name="com.activeindexing.advisor.product.template.ProductBranch" proxy="com.activeindexing.advisor.product.template.ProductBranch" discriminator-value="2">
<property name="distributionType" column="distribution_type" type="string"/>
<list name="childList" table="product_template_node_child_list" lazy="false">
<key column="node_id"/>
<index column="list_position"/>
<many-to-many column="child_node_id" class="com.activeindexing.advisor.product.template.TemplateNode"/>
</list>
</subclass>
</class>
Code:
package com.activeindexing.advisor.product.template;
import java.io.Serializable;
import com.activeindexing.advisor.product.ProductPath;
public abstract class TemplateNode implements Serializable {
private TemplateNode parent;
private ProductPath productPath;
private String productName;
private long id;
protected TemplateNode() {}
public TemplateNode (String productName, TemplateNode parent) {
this.productName = productName;
this.parent = parent;
if (parent == null) {
productPath = new ProductPath();
}
else {
productPath = new ProductPath(parent.getProductPath());
}
productPath.addPath(productName);
}
public String getProductName () {
return productName;
}
public TemplateNode getParent () {
return parent;
}
public ProductPath getProductPath () {
return productPath;
}
public abstract boolean isLeaf ();
public abstract TemplateNode clone (TemplateNode clonedParent);
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public void setParent(TemplateNode parent) {
this.parent = parent;
}
public void setProductName(String productName) {
this.productName = productName;
}
public void setProductPath(ProductPath productPath) {
this.productPath = productPath;
}
}
Code:
package com.activeindexing.advisor.product.template;
import java.util.LinkedList;
import java.util.List;
import com.activeindexing.advisor.product.template.distribution.DistributionManager;
import com.activeindexing.advisor.product.template.print.DistributionTracker;
public class ProductBranch extends TemplateNode {
private String distributionType;
private List<TemplateNode> childList;
public ProductBranch() {
super();
childList = new LinkedList<TemplateNode>();
}
public ProductBranch (String productName, TemplateNode parent) {
super(productName, parent);
childList = new LinkedList<TemplateNode>();
}
public ProductBranch (String productName, TemplateNode parent, String distributionType) {
super(productName, parent);
this.distributionType = distributionType;
childList = new LinkedList<TemplateNode>();
}
public ProductBranch (ProductBranch productBranch, TemplateNode clonedParent) {
super(productBranch.getProductName(), clonedParent);
TemplateNode[] childNodes;
distributionType = productBranch.getDistributionType();
childNodes = productBranch.getChildren();
for (int count = 0; count < childNodes.length; count++) {
addChild(childNodes[count].clone(this));
}
this.setId( productBranch.getId() );
}
public boolean isLeaf () {
return false;
}
public String getDistributionType () {
return distributionType;
}
public double getWeight (DistributionTracker distributionTracker, TemplateNode child) {
DistributionManager distributionManager;
distributionManager = distributionTracker.getDistributionManager(this);
if (getParent() == null) {
return distributionManager.getWeight(child);
}
else {
return ((ProductBranch)getParent()).getWeight(distributionTracker, this) * distributionManager.getWeight(child);
}
}
public synchronized void addChild (TemplateNode child) {
childList.add(child);
}
public synchronized TemplateNode[] getChildren () {
TemplateNode[] children;
children = new TemplateNode[childList.size()];
childList.toArray(children);
return children;
}
public TemplateNode clone (TemplateNode clonedParent) {
return new ProductBranch(this, clonedParent);
}
public List getChildList() {
return this.childList;
}
public void setChildList(List childList) {
this.childList = childList;
}
public void setDistributionType(String distributionType) {
this.distributionType = distributionType;
}
}
Code:
package com.activeindexing.advisor.product.template;
import com.activeindexing.advisor.market.index.IndexIdentifier;
import com.activeindexing.advisor.product.template.print.DistributionTracker;
public class IndexLeaf extends TemplateNode {
private IndexIdentifier indexIdentifier;
public IndexLeaf() {
super();
}
public IndexLeaf (String productName, TemplateNode parent, String indexProvider, String indexName, String[] strategicFractionNames) {
super(productName, parent);
indexIdentifier = new IndexIdentifier(indexProvider, indexName, strategicFractionNames);
}
public IndexLeaf (IndexLeaf indexLeaf, TemplateNode clonedParent) {
super(indexLeaf.getProductName(), clonedParent);
indexIdentifier = indexLeaf.getIndexIdentifier();
this.setId( indexLeaf.getId() );
}
public boolean isLeaf () {
return true;
}
public IndexIdentifier getIndexIdentifier () {
return indexIdentifier;
}
public double getWeight (DistributionTracker distributionTracker) {
if (getParent() == null) {
return 1.0D;
}
return ((ProductBranch)getParent()).getWeight(distributionTracker, this);
}
public TemplateNode clone (TemplateNode clonedParent) {
return new IndexLeaf(this, clonedParent);
}
public void setIndexIdentifier(IndexIdentifier indexIdentifier) {
this.indexIdentifier = indexIdentifier;
}
}
Code:
package com.activeindexing.advisor.product.template;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
public class TemplateWalker implements Iterator<TemplateNode> {
public static enum Traversal {
BRANCHES, LEAVES, BOTH
};
private LinkedList<TemplateNode> nodeList;
private Traversal traversal;
public TemplateWalker (TemplateNode templateNode, Traversal traversal) {
this.traversal = traversal;
nodeList = new LinkedList<TemplateNode>();
if ((!traversal.equals(Traversal.BRANCHES)) || (!templateNode.isLeaf())) {
nodeList.add(templateNode);
}
}
public boolean hasNext () {
return (!nodeList.isEmpty());
}
public TemplateNode next () {
TemplateNode templateNode;
TemplateNode[] children;
if (nodeList.isEmpty()) {
throw new NoSuchElementException();
}
do {
templateNode = nodeList.removeFirst();
if (!templateNode.isLeaf()) {
children = ((ProductBranch)templateNode).getChildren();
for (int count = 0; count < children.length; count++) {
if ((!traversal.equals(Traversal.BRANCHES)) || (!children[count].isLeaf())) {
nodeList.add(children[count]);
}
}
}
} while (traversal.equals(Traversal.LEAVES) && (!templateNode.isLeaf()));
return templateNode;
}
public void remove () {
throw new UnsupportedOperationException();
}
}
Code:
java.lang.ClassCastException: com.activeindexing.advisor.product.template.TemplateNode$$EnhancerByCGLIB$$80dd16ee
at com.activeindexing.advisor.product.template.TemplateWalker.next(TemplateWalker.java:46)
I am using Hibernate 3.0 and JDK 1.5