Hi all,
I'm trying to persist a tree structure. Here class A
references several A's (as his children -> OneToMany), and one A(p) (as
his parent -> ManyToOne). When JPA is parsing my metadata a
"StackOverflowError" exception is thrown. Seems to be the typical
recursive problem because of the self-referencing foreign key (=a
foreign key to the same table) created.
I haven't seend any referente in the manual to this
scenario.
Has anyone try this before? Is this feature supported by
openJPA/JPA? Should i try one of the standard sql approches ("Adjacency
List Model", "The Path Enumeration Model", "Nested Set Model of
Hierarchies"..), or is completely unsupported?
Thanks in advance
Here is the class, and its corresponding Id class:
/////Owner///////
package com.covansys.routingengine.functionalcore;
import javax.persistence.*;
import org.apache.openjpa.persistence.ElementDependent;
import com.covansys.routingengine.ifc.jpa.ScreeningElementId;
import java.util.*;
@Entity
@IdClass(com.covansys.routingengine.ifc.jpa.OwnerId.class)
public class Owner extends OwnerEntity implements Comparable
{
@Id
protected String label;
@Id
@ManyToOne
protected Owner owner;
/**
* <p>
* This function returns the value of the owner member
* </p>
* @return owner, Owner object which contains the owner
member value
*/
public Owner getOwner()
{
return owner;
}
/**
* <p>
* This function sets the owner value to the value of the
owner passed
* as argument. If the value of the targetOwner is null then
it sets its
* value to the same owner.
* </p>
* @param o Owner object to be set as owner
*/
public void setOwner(Owner o)
{
owner = o;
}
/**
* <p>
* This function returns the value of the label member
* </p>
* @return label, String which contains the label member
value
*/
public String getLabel()
{
return label;
}
/**
* <p>
* This function sets the value of the label member to the
value
* of the String passed as argument
* </p>
* @param l String to be set as label
*/
public void setLabel(String l)
{
label = l;
}
@ElementDependent
@OneToMany(mappedBy="owner", cascade={CascadeType.ALL})
private Set<Owner> children;
@Basic
private String tag;
public Owner()
{
children = new HashSet<Owner>();
}
public void setOwnerId(long id)
{
//ownerId= id;
}
public long getOwnerId()
{
//return ownerId;
return 0;
}
public int compareTo(Object o)
{
if (o instanceof Owner)
{
Owner owner = (Owner)o;
return
getLabel().compareTo(owner.getLabel());
} else {
//put behind
return 1;
}
}
/*public int hashCode() {
return ((label == null) ? 0 : label.hashCode())
^ ((owner == null) ? 0 : owner.hashCode());
} */
public boolean equals(Object o)
{
if (this == o) return true;
if (o instanceof Owner)
{
Owner owner = (Owner)o;
//return this.getOwner() ==
owner.getOwner() && getLabel().equals(owner.getLabel());
return
getLabel().equals(owner.getLabel());
} else {
return false;
}
}
public boolean isChild(Owner o)
{
if (o == null )
{
return false;
} else {
if (equals(o)) {
return true;
} else {
boolean found = false;
Iterator<Owner> it =
children.iterator();
Owner child = null;
while(it.hasNext() &&
!found) {
child =
it.next();
found =
child.isChild(o);
}
return found;
}
}
}
public void setTag(String t)
{
tag = t;
}
public String getTag()
{
return tag;
}
public void addChild(Owner o)
{
children.add(o);
o.setOwner(this);
}
public void removeChild(Owner o)
{
children.remove(o);
}
public void removeAllChildren()
{
for (int i = 0 ; i < children.size(); i ++)
children.remove(i);
}
public Collection<Owner> getChildren()
{
return children;
}
public List<Owner> getAllChildren()
{
List<Owner> allChildren = new Vector<Owner>();
for(Owner oAux : children)
{
allChildren.addAll(oAux.getAllChildren());
}
return allChildren;
}
public Owner searchChild(String label) throws OwnerNotFound
{
Owner oAux = new Owner();
oAux.setLabel(label);
return searchChild(oAux);
}
public Owner searchChildByTag(String t) throws OwnerNotFound
{
if (t == null )
{
throw new OwnerNotFound();
} else {
if (t.equals(this.tag))
{
return this;
} else {
boolean found = false;
Iterator<Owner> it =
children.iterator();
Owner child = null;
Owner oAux = null;
while(it.hasNext() &&
!found)
{
try
{
child = it.next();
oAux = child.searchChildByTag(t);
found = true;
} catch
(Exception e) {
}
}
if (found)
{
return oAux;
} else {
throw new
OwnerNotFound();
}
}
}
}
public Owner searchChild(Owner o) throws OwnerNotFound
{
if (o == null )
{
throw new OwnerNotFound();
} else {
if (equals(o))
{
return this;
} else {
boolean found = false;
Iterator<Owner> it =
children.iterator();
Owner child = null;
Owner oAux = null;
while(it.hasNext() &&
!found)
{
try
{
child = it.next();
oAux = child.searchChild(o);
found = true;
} catch
(Exception e) {
//this child don't have the owner, try with the next
}
}
if (found)
{
return oAux;
} else {
throw new
OwnerNotFound();
}
}
}
}
}
////////end owner///////
//////////OwnerId//////////
package com.covansys.routingengine.ifc.jpa;
import java.util.List;
import com.covansys.routingengine.functionalcore.Owner;
public class OwnerId
{
public String label;
public String owner;
public boolean equals(Object other) {
if (other == this)
return true;
if (!(other instanceof OwnerId))
return false;
OwnerId mi = (OwnerId) other;
return (label == mi.label
|| (label != null && label.equals(mi.label)))
&& (owner == mi.owner
|| (owner != null && owner.equals(mi.owner)));
}
public int hashCode() {
return ((label == null) ? 0 : label.hashCode())
^ ((owner == null) ? 0 : owner.hashCode());
}
}
/////////end ownerid/////////
Confidentiality Statement:
This message is intended only for the individual or entity to which it is
addressed. It may contain privileged, confidential information which is exempt
from disclosure under applicable laws. If you are not the intended recipient,
please note that you are strictly prohibited from disseminating or distributing
this information (other than to the intended recipient) or copying this
information. If you have received this communication in error, please notify us
immediately by return email.
-----------------------------
